On Sun, Apr 23, 2017 at 9:12 AM, <[email protected]> wrote: > Tatu, > > I got this working as per your comment (to remove any @JsonType and > hand-craft the serialization/deserialization of the type information). I've > got that going in the 2nd version of the code as checked in here: > https://github.com/hexastax/miscellaneous-java-projects/tree/master/json-serde-1. > > I'm really curious as to whether a) this is the right way to go or there's a > better approach, perhaps something more explicit with > TypeSerializer/TypeDeserializer? > > The other issue is what happens in the Document class. Basically, I'm > looking for advice on the best practice of safe and "proper" > serialization/deserialization of a "property bag". Say you have a > Map<String, List<Object>> in hand and you want 'good' JSON > serialization/deserialization of that. > > I've got it 'somewhat working' with hand-crafted handling of things like all > the basic types, Date, DOM and null values, but not yet sure what to do with > a "random POJO" or if anything special needs to be done for a Collection or > a Map that happens to be one of the values in one of the List<Object> in the > map. > > I'd very much like to move away from having to hand-craft the handling of > various data types. Along with that, if I can move away from custom > serializer/deserializer on this 'property bag' object (Document) then > perhaps I can move away from hand-crafting of the polymorphic type handling. > > Any recommendations would be appreciated.
Sounds like good progress. Unfortunately this is a difficult problem to handle in general... partly since JSON as a format has no concept of metadata, so whereas in XML certain things (like type ids, say) can be stashed in namespaced attributes, or in YAML can be stored as separate aspects (anchors, type tags), JSON stores it all as data, and there are no standards or even wide-spread naming conventions to rely on. So: what Jackson does is require help of Java type definitions, where applicable, and support for a limited set of structural conventions (type-as-named-property, type-as-wrapper-array-element, type-as-object-key-wrapper). Extensibility that there is, then, only covers these patterns. If I had to define general-purpose round-trippable (end-to-end) serialization using JSON, I would probably standardize on use of "wrapper array" approach, so that every single value is a two-element array: first being type identifier String, and second value actual type. This results in "ugly" JSON, and some bloat (not minimal representation), but can reliable preserve and round-trip type information. Jackson does support this format; the only thing you'd need is to force default typing applied to all values (minus small set of "native" types, most importantly String -- this gives small space saving without losing round-trip aspect). On the other hand, if you want JSON that "looks good", you get in trouble trying to represent arbitrary set of data. Mixing Maps/Collections with typed POJOs and Scalars (dates) is a quagmire in JSON. Not sure if above helps; it's more a dump of some of my thoughts based on implementing polymorphic type handling, and supporting it for past 5+ years. -+ Tatu +- > > - Dmitry > > > On Friday, April 21, 2017 at 1:10:44 PM UTC-4, [email protected] wrote: >> >> Hi Tatu, >> >> Thanks for your response. >> >> On the first issue, with polymorphic json serde, I'm still grappling with >> the how-to for including the class info handling without the annotations. >> >> The second issue is, the reasoning behind having custom serde on the >> superclass (Document) to begin with. I had originally run into some JSON >> output formatting issues as well as handling of specific data types such as >> dates and DOM's. There is some (cumbersome) logic on Document which >> currently produces the format we like but has a lot of hand-crafting of data >> type handling which we'd love to get rid of. Also it has issues with >> dealing with "random" embedded objects and collection types. >> >> I've summarized everything as a Java maven module and made it available >> here: >> >> https://github.com/hexastax/miscellaneous-java-projects/tree/master/json-serde-1 >> >> MessageTest shows the issues with the first issue, and DocumentTest shows >> issues with the second issue. There's also a README file there with the >> TODO's identified. >> >> I'd really appreciate your review and some recommendations! >> Thanks, >> - Dmitry >> >> >> On Wednesday, April 19, 2017 at 8:14:18 PM UTC-4, [email protected] >> wrote: >>> >>> Hi, >>> >>> We have the following object hierarchy: >>> >>> - Document >>> - abstract Resource extends Document >>> - Message extends Resource >>> >>> We want to be able to serialize Message to JSON and then deserialize it >>> without necessarily referencing Message.class, i.e. we want to go >>> polymorphic: >>> >>> 1) Message msg = om.readValue(strJson, Message.class); >>> and >>> 2) Resource res = om.readValue(strJson, Resource.class); >>> >>> This is working: >>> 3) Document doc = om.readValue(strJson, Document.class) but not the other >>> two ways (1 and 2). >>> >>> Currently, the serialization is specified as follows: >>> >>> Document has: @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, >>> include=As.WRAPPER_OBJECT) >>> Document has: @JsonSerialize(using = JsonDocumentSerializer.class) >>> Document has: @JsonDeserialize(using = JsonDocumentDeserializer.class) >>> Resource initially had no specific annotations >>> Next, tried Resource with: @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, >>> include=As.WRAPPER_OBJECT), also @JsonSubTypes({ @Type=Message.class) }) >>> Message has @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, >>> include=As.WRAPPER_OBJECT) >>> The JsonDocumentSerializer extends JsonSerializer<Document> and has >>> custom logic for serializing a Document. >>> The JsonDocumentDeserializer extends JsonDeserializer<Document> and has >>> custom logic for deserializing a Document. >>> We would very much like not to have @JsonSubTypes on Document (it's in a >>> higher level module) >>> >>> Message seems to be getting serialized properly, with >>> { >>> "com.myco.Message": >>> { "id": "id goes here" >>> ........................................ >>> } >>> For that, we had to override the serializeWithType method in >>> JsonDocumentSerializer. >>> >>> However, I can't get a Resource, or a Message returned from the readValue >>> method. >>> >>> We have tried: >>> >>> objectMapper.enableDefaultTyping() >>> In JsonDocumentDeserializer: >>> >>> @Override >>> public Object deserializeWithType(JsonParser jp, DeserializationContext >>> ctxt, >>> TypeDeserializer typeDeserializer) >>> throws IOException, JsonProcessingException >>> { >>> return typeDeserializer.deserializeTypedFromObject(jp, ctxt); >>> } >>> >>> but none of that seems to have worked. >>> >>> Any other recommendations? >>> Thanks, >>> - Dmitry >>> >>> >>> > -- > You received this message because you are subscribed to the Google Groups > "jackson-user" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "jackson-user" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. For more options, visit https://groups.google.com/d/optout.
