serializr icon indicating copy to clipboard operation
serializr copied to clipboard

[Feature] context for serialization

Open nros opened this issue 7 years ago • 13 comments

deserialization uses a Context with all deserializers. Custom serializers become more flexible if the serialization process uses the same mechanism.

purpose

support automatic creation of references with a custom serializer.

explanation

A context can be used as a place to store temporary data for serialization. A custom serializer can make use of this temporary data to keep track on all serialized objects and serialize only IDs for those, that have already been serialized. Of course, the companion custom deserializer need to know about such IDs, decode them and behave much like the deserializer of reference().

All this would be impossible without keeping track on all already serialized entities.

nros avatar Nov 07 '17 23:11 nros

Coverage Status

Coverage increased (+0.5%) to 92.57% when pulling 503784b0064154c5f0b57767bf7447bfec1119c1 on nros:feature_serialize-context into 59fe6e569ec72c102bc8ed3a2ec3697edea35bf0 on mobxjs:master.

coveralls avatar Nov 07 '17 23:11 coveralls

Coverage Status

Coverage increased (+0.5%) to 92.585% when pulling a80c0c01b2e43dbd7c973666e39c48c74999a2c0 on nros:feature_serialize-context into 59fe6e569ec72c102bc8ed3a2ec3697edea35bf0 on mobxjs:master.

coveralls avatar Nov 08 '17 01:11 coveralls

Coverage Status

Coverage increased (+0.5%) to 92.702% when pulling dfed41d1df02900c6604f5d42fb5f58562ef2714 on nros:feature_serialize-context into c85a6376fdc535ace2661e5a35686e1928d53901 on mobxjs:master.

coveralls avatar Nov 08 '17 10:11 coveralls

Thanks to these changes, I was able to create a custom serializer/deserializer that keeps track on all serialized entities and automatically stores only a reference (as the ID) in case the entity has already been serialized. This avoids breaking up in-memory references during serialization and creating duplicates upon deserializing.

To make that work, I had to tackle #65 as well with this custom serializer. So the serializer stores a class identifier along the serialized data and uses a dependency injection system to create instances for this class identifier upon deserialization.

Using a custom serializer to support these features seems less invasive than changing serializr itself. So maybe this will help others too.

I would appreciate if you accept this PR, although some internal functions are exposed. This is only done for the good, to make custom serializers integrate better with serializr, like benefitting from the reference resolving system.

nros avatar Nov 08 '17 10:11 nros

I’m busy recently, I would have spare time to review this feauture seriously until weekend ... I reply to this just let you know we saw your nice works. 👍

chengjianhua avatar Nov 08 '17 17:11 chengjianhua

@nros let's hold off on this PR until we finish the discussion on #65

alexggordon avatar Nov 08 '17 20:11 alexggordon

@nros I need exactly this, along with the support for containers of polymorphic objects. I've pulled your feature branch for this, but I am new to serializr (and Javascript - using Typescript actually), so a rough example of your custom serializer/deserializer maintaining the context would be very helpful for me. By the way, I implemented a scheme that works like this in C++ over 20 years ago and have been using it ever since in applications built from plugins.

spinorkit avatar Dec 06 '17 04:12 spinorkit

@nros to achieve what I envisage at the top level, I would like to pass a context object to the serialize<T>() function (and the deserialize<T>() function) so that I can control the lifetime of the dictionary of references. I would like to pass the reference dictionary filled in when serializing a full snapshot of the state of the app to subsequent calls to serialize() for incremental actions that occur after the snapshot is written. I currently can't see how to achieve this control with a custom serializer alone.

spinorkit avatar Dec 06 '17 13:12 spinorkit

@spinorkit see this example: https://gist.github.com/nros/7791baca1927ee6b25e790da76544d99

nros avatar Mar 21 '18 11:03 nros

This is almost a year old by now. Any hope for it being merged? I have exactly the same use case - I need to serialize cyclic graph, preferably in a way compatible with json.net

tkolo avatar Oct 02 '18 17:10 tkolo

@nros @spinorkit I am happy to have a look at this, if there is still a need. However, please provide some test cases, that can be a basis for the discussion of the optimal API changes. Ideally you can make some respective enhancements in test/typescript/ts.ts for the PR

1R053 avatar Feb 10 '19 10:02 1R053

**Update: ** I think I misunderstood the intent of this PR. I might put this suggestion in a separate issue.

~I believe this same feature could easily be achieved by defining this function~

export function deserializeWithContext(context: Context, _class: any, serialized: any) {
  return deserializeObjectWithSchema(context, getDefaultModelSchema(_class)!, serialized, () => {}, undefined);
}

~deserializeObjectWithSchema is (defined below)~ https://github.com/mobxjs/serializr/blob/69fed6f55bf04a2cfa07dd8cb5863af7a44be9a8/src/core/deserialize.ts#L120 ~But it is not a part of the serializr public api, and thus it is not re-exported by serializr~

peey avatar Mar 18 '21 11:03 peey

It's been a while. The project depending on this fix has already been abondoned and replaced by a Java+Vue re-implementation. I'll do my best to update my MR and provide some test cases within the next weeks.

nros avatar Mar 21 '21 16:03 nros