users@jsonb-spec.java.net

[jsonb-spec users] [jsr367-experts] Re: Re: Re: Re: Re: Re: Re: Re: Java polymorphism support

From: Romain Manni-Bucau <rmannibucau_at_tomitribe.com>
Date: Thu, 31 Mar 2016 16:58:07 +0200

Hi Roman

This just doesn't match the end user need, see my comments inline

2016-03-31 16:32 GMT+02:00 Roman Grigoriadi <roman.grigoriadi_at_oracle.com>:

> Hi,
>
> If we are about to consider Serializers/Deserializers in future, there
> would be no JsonStructure in deserializer. Neither it will pe possible to
> pass an arbitrary object to JsonGenerator. You will do your business
> directly on JSONP JsonGenerator/JsonParser, which doesn't support those
> feautures. If you want to marshall any arbitrary object to/from json use an
> adapter.
>
> Adapters can also be used for working with JsonStructure, it may look like
> this:
>
> public class BoxToJsonObjectAdapter implements JsonbAdapter<Box, JsonObject> {
> @Override public JsonObject adaptToJson(Box obj) throws Exception {
> [1] final JsonObjectBuilder builder = JsonProvider.provider().createObjectBuilder(); //this is a standard api of javax.json you can build any JSON object with it
> builder.add("boxStrField", obj.getBoxStrField());
> [2] builder.add("boxIntegerField", obj.getBoxIntegerField());
> return builder.build();
> }
>
> @Override public Box adaptFromJson(JsonObject jsonObj) throws Exception {
> Box box = new Box();
> box.setBoxStrField(jsonObj.getString("boxStrField"));
> box.setBoxIntegerField(jsonObj.getInt("boxIntegerField"));
> return box;
> }
> }
>
> You can convert any object directly to / from JsonStructure, which is
> supported to be serialized / deserialized transparently than. It may than
> supplement Serializer/Deserializer like functionality.
>
>
[1] that's something which should 100% be handled by the jsonp runtime: the
provider access. Suppose jsonb can select the provider it needs - we'll
need it anytime soon but that's another topic - then here you don't want to
have to re-configure the provider you maybe don"t know at that moment. So
the provider at least should be provided by jsonb.
[2] this is a simple case but the simplest next need is: "serialize this
object": would you recreate another Jsonb instance there and potentially
loose the "current" config? So instead of getting injected JsonProvider
getting a JsonbSerializer or whatever name we want "extending"
JsonObjectBuilder to have a add(objectToSerializeWithJsonb) and
add(fieldName, objectToSerializeWithJsonb) can work.

That's for the pitfalls. That said I like the idea of going back on
JsonObject in adapters for these advanced cases. It is less low level than
JsonbGenerator but still need this small jsonp-jsonb glue API:

public class BoxToJsonObjectAdapter implements JsonbObjectAdapter<Box>
{ // particular type of adapter working with jsonbobejct
    @Override public JsonbObject adaptToJson(JsonbObjectBuilder
builder, Box obj) throws Exception {

        builder.add("type", obj.getClass().getName());
        builder.add("value", obj); // new method linking jsonb-jsonp
        return builder.build();
    }

    @Override public Box adaptFromJson(JsonbObject obj) throws Exception {
        return obj.getObject( // new method linking jsonp and jsonb

                      loadClass(jsonObj.getString("type")));

    }
}

This solution introduces a particular type of adapter which can get the
builder/object and it works for all cases but the primitive one (date as
string to joda.LocalDate for instance) where current adapters still makes
sense I think. If we want to have a single type of adapter we just replace
JsonbObject by JsonbStructure in previous example and define JsonbValue,
JsonbObject and JsonbArray I guess.


Wdyt?




> Thanks,
> Roman
>
>
> On 03/24/2016 12:27 PM, Romain Manni-Bucau wrote:
>
> Hmm, here how I see things:
>
> - Adapters are insanely great for end users (I include myself there) cause
> it is easy to implement but they are limited by design cause you get a
> model and return another model, so no in between processing (+ it can be
> super verbose in some cases)
> So
> - We need a lower level API where you can, without creating any model,
> serialize using jsonp + a thin layer on top integrating with the mapper
>
> So we would get the business adapters (current ones) and the technical
> ones ("(De)Serializer"?). This would allow all users to do any fancy things
> when needed - and even if 20% of the cases it is a real life need - keeping
> by default a smooth API.
>
> I don't think it is a lot of work since we already discussed it a bit in
> this thread and cause jackson, the RI implementations (and probably other)
> already have such an API.
>
> Si it would need:
>
> - JsonbGenerator (extends JsonGenerator { void write(String field, Object
> object); void write(Object object) }), JsonbReader (extends JsonReader) { T
> read(Type type)}
> - Serializer { void serialize(T object, JsonbGenerator) }/Deserializer{ T
> deserialize(JsonStructure json, JsonbReader reader) } API
> - JsonbConfig with(De)Serializers() methods
>
> Side note: this also handle more advanced cases I encountered working with
> ElasticSearch where you need to modify the way the mapper serialize the
> model at runtime. More generally anytime you try to provide a framework you
> need such trick cause you don't fully control the model and you don't want
> to rescan the whole model (= reimplement a part of the mapper).
>
> Wdyt?
>
>
>
> Romain Manni-Bucau
> @rmannibucau
> http://www.tomitribe.com
> http://rmannibucau.wordpress.com
> https://github.com/rmannibucau
>
> 2016-03-24 12:14 GMT+01:00 Roman Grigoriadi <roman.grigoriadi_at_oracle.com>:
>
>> It depends if we include TypeWrapperAdapter into spec and API. If not,
>> than yes it would be a proprietary of jsonb-ri.
>>
>> Roman.
>>
>>
>> On 03/24/2016 12:09 PM, Romain Manni-Bucau wrote:
>>
>> Am I right saying it uses a proprietary API to work?
>>
>> If so I think my JsonbGenerator/JsonbReader are a standardization of such
>> API and what Mark proposed as well. Then maybe we can discuss their
>> integration in the spec?
>> Le 24 mars 2016 12:03, "Roman Grigoriadi" <roman.grigoriadi_at_oracle.com>
>> a écrit :
>>
>>> Hi,
>>>
>>> @Romain - I added a test -
>>> org.eclipse.persistence.json.bind.adapters.PolymorphismAdapterTest.
>>> It uses these pojos:
>>>
>>> public static class Animal {
>>> public String name;}
>>> public static class Dog extends Animal {
>>> public String dogProperty;}
>>> public static class Cat extends Animal {
>>> public String catProperty;}
>>> public static class Pojo {
>>> public Animal animal; public List<Animal> listOfAnimals = new ArrayList<>();}
>>>
>>> and generates this JSON for accordingly instantiated pojo:
>>>
>>> {
>>> "animal":{
>>> "className":"org.eclipse.persistence.json.bind.adapters.PolymorphismAdapterTest$Dog",
>>> "instance":{
>>> "name":"Ralph",
>>> "dogProperty":"Property of a Dog."
>>> }
>>> },
>>> "listOfAnimals":[
>>> {
>>> "className":"org.eclipse.persistence.json.bind.adapters.PolymorphismAdapterTest$Cat",
>>> "instance":{
>>> "name":"Snowball",
>>> "catProperty":"Property of a Cat."
>>> }
>>> },
>>> {
>>> "className":"org.eclipse.persistence.json.bind.adapters.PolymorphismAdapterTest$Dog",
>>> "instance":{
>>> "name":"Ralph",
>>> "dogProperty":"Property of a Dog."
>>> }
>>> }
>>> ]
>>> }
>>>
>>> An
>>> org.eclipse.persistence.json.bind.internal.unmarshaller.TypeWrapperItem
>>> class is responsible for
>>> *"how "Jsonb handles such event with creating instance of appropriate
>>> type"". *Please see it at eclipselink repo
>>> <http://git.eclipse.org/c/eclipselink/eclipselink.runtime.git>, master
>>> branch. The Jsonb project is in eclipselink-runtime/jsonb folder.
>>>
>>> I don't know what are the internals of Johnzon, but I suppose it will
>>> also include some custom handling for specified attribute in case of
>>> TypeWrapper class. Maybe I just missed to specify explicitly in previous
>>> communication, that I have to add this custom handling in JSONB. Of course
>>> it will never work without it..
>>>
>>> Regards,
>>> Roman
>>>
>>> On 03/23/2016 02:26 PM, Romain Manni-Bucau wrote:
>>>
>>> Will wait for the test cause I really don't see how "Jsonb handles such
>>> event with creating instance of appropriate type" but wanted to share the
>>> read before write solution works even if not elegant using the
>>> typewrapper/adatper we spoke about:
>>>
>>>
>>> public void ploymorphism() { // we run it since it checked list/item
>>> conversion
>>>
>>> final Bar bar = new Bar(); // ~your Animal
>>>
>>> bar.value = 11;
>>>
>>>
>>> final Bar2 bar2 = new Bar2();
>>>
>>> bar2.value = 21;
>>>
>>> bar2.value2 = 22;
>>>
>>>
>>> final Polymorphism foo = new Polymorphism(); // the pojo with a
>>> collection of bars
>>>
>>> foo.bars = new ArrayList<>(asList(bar, bar2));
>>>
>>>
>>> final Jsonb jsonb = JsonbBuilder.create(
>>>
>>> new JsonbConfig()
>>>
>>> .setProperty("johnzon.readAttributeBeforeWrite", true) // NOT STANDARD,
>>> enforces to use the getter to determine the type to deserialize
>>>
>>> .withPropertyOrderStrategy(PropertyOrderStrategy.LEXICOGRAPHICAL) /*
>>> assertEquals() order */);
>>>
>>>
>>> final String toString = jsonb.toJson(foo);
>>>
>>> assertEquals("{\"bars\":[" +
>>>
>>> "{\"type\":\"org.apache.johnzon.jsonb.AdapterTest$Bar\",\"value\":{\"
>>> value\":11}}," +
>>>
>>> "{\"type\":\"org.apache.johnzon.jsonb.AdapterTest$Bar2\",\"value\":{\"
>>> value\":21,\"value2\":22}}]}", toString);
>>>
>>>
>>> final Polymorphism read = jsonb.fromJson(toString, Polymorphism.class);
>>>
>>> assertEquals(2, read.bars.size());
>>>
>>> assertEquals(11, read.bars.get(0).value);
>>>
>>> assertTrue(Bar.class == read.bars.get(0).getClass());
>>>
>>> assertEquals(21, read.bars.get(1).value);
>>>
>>> assertTrue(Bar2.class == read.bars.get(1).getClass());
>>>
>>> assertEquals(22, Bar2.class.cast(read.bars.get(1)).value2);
>>>
>>> }
>>>
>>>
>>>
>>>
>>> 2016-03-23 14:18 GMT+01:00 Roman Grigoriadi <
>>> <roman.grigoriadi_at_oracle.com>roman.grigoriadi_at_oracle.com>:
>>>
>>>>
>>>>
>>>> On 03/23/2016 02:02 PM, Romain Manni-Bucau wrote:
>>>>
>>>>
>>>>
>>>> 2016-03-23 13:39 GMT+01:00 Roman Grigoriadi <
>>>> <roman.grigoriadi_at_oracle.com>roman.grigoriadi_at_oracle.com>:
>>>>
>>>>> I think [A] is misunderstood..
>>>>>
>>>>>
>>>>>
>>>>> *[A] Think I get it: the adapter will return Foo and then on this
>>>>> instance Jsonb will populate fields. * That is not what I ment. An
>>>>> adapter is at the end of the process, T instance is already populated both:
>>>>> when adapter adapts it returns adapted result.
>>>>> Above statement is maybe enough, but for sake of clarity let me
>>>>> revisit whole process.
>>>>>
>>>>> 1. Lets have JSON document for a TypeWrapper<T>
>>>>> {
>>>>> "animal":{
>>>>> "className":"com.foo.Dog",
>>>>> "instance":{
>>>>> "name":"Doggie",
>>>>> "dogProperty":"Property of a Dog."
>>>>> }
>>>>> }
>>>>> }
>>>>>
>>>>> During deserialization what happens first is a completed instance of a
>>>>> TypeWrapper with a a fully populated T inside. This happens in following
>>>>> steps:
>>>>> 1. Jsonb encounters deserializing a TypeWrapper<T>, and processes it
>>>>> custom TypeWrapperDeserializer.
>>>>> 2. TypeWrapperDeserializer (implemented by us), creates an empty
>>>>> instance of TypeWrapper.
>>>>> 3. Jsonb reads and sets property "className" into TypeWrapper
>>>>> 4. Jsonb loads a class by this classname and creates instance with
>>>>> default construcotor in our case Dog or Cat and sets it to TypeWrapper
>>>>> instance.
>>>>>
>>>>
>>>> That's where I'm lost. Only way it could work - without putting this
>>>> behavior in the spec - is if TypeWrapper overrides the setter of classname
>>>> to also set the instance:
>>>>
>>>> public void setClassName(final String className) {
>>>> this.className= className;
>>>> try {
>>>> this.value = Animal.class.cast(Thread.currentThread().getContextClassLoader().loadClass(className).newInstance());
>>>> } catch (final InstantiationException | IllegalAccessException | ClassNotFoundException e) {
>>>> throw new IllegalArgumentException(e);
>>>> }
>>>> }
>>>>
>>>> Nope, it is only the className set as a String in this moment.
>>>> Next JsonParser enconters a JsonObject and pushes ObjectStarted event
>>>> into JSONB. Jsonb handles such event with creating instance of appropriate
>>>> type. That type is normally read from ClassModel (which is read from actual
>>>> Field or ParameterizedType argument of a Collection). But in our case this
>>>> type is swapped with a Class loaded dynamically by name.
>>>>
>>> So now we have a correct instance ready to be populated by common
>>>> reflection deserialization.
>>>>
>>>> And then Jsonb before creating the Animal instance reads the field to
>>>> extract its type which is likely not what is done since the type is deduced
>>>> statically from the model class (field type) - this part is important to
>>>> avoid surprises and open security issues.
>>>>
>>>> No need to create instance now, it is already fully populated. Just
>>>> extract it from TypeWrapper as is.
>>>>
>>>>
>>>> If I'm still wrong do you care writing a small test case showing that
>>>> in action please?
>>>>
>>>> Sure I will implement a test and push it to our eclipselink git which
>>>> hosts the jsonb-ri.
>>>>
>>>>
>>>> 5. Jsonb parses a "ClassModel" for Dog or Cat class (reading all @Jsonb
>>>>> annots etc if needed).
>>>>> 6. Jsonb goes deeper in json document parsing json object for
>>>>> "instance" property and populating all fields in Dog or Cat (doesn't really
>>>>> care what is it as it is common reflection based process for all properties
>>>>> inside).
>>>>> 7. After above is completed an instance of TypeWrapper with fully
>>>>> deserialized T inside is passed to an adapter method "T
>>>>> adaptFromJson(TypeWrapper<T> obj)".
>>>>> 8. Result from adapter is than set to a field, setter, collection,
>>>>> map, array or whatever else is declared in domain model to unmarshall into.
>>>>>
>>>>> What returns an adapter is already ready to be set into model as is
>>>>> with polymorphism working this way.
>>>>>
>>>>> Now I suppose this is exactly what:
>>>>> [A]....*"Thought adapter should return a populated instance otherwise
>>>>> no way to convert to business model properly IMO"* means ?
>>>>>
>>>>> Hope this helps and will bring some light.
>>>>>
>>>>> Thanks,
>>>>> Roman
>>>>>
>>>>>
>>>>>
>>>>> On 03/23/2016 12:49 PM, Romain Manni-Bucau wrote:
>>>>>
>>>>>
>>>>> 2016-03-23 12:29 GMT+01:00 Roman Grigoriadi <
>>>>> <roman.grigoriadi_at_oracle.com>roman.grigoriadi_at_oracle.com>:
>>>>>
>>>>>> You load a Dog or Cat class by name, which appears in json and
>>>>>> instantiate it with default constructor. This is what I suppose a custom
>>>>>> deserializer for TypeWrapper would do.
>>>>>>
>>>>>>
>>>>> [A] Think I get it: the adapter will return Foo and then on this
>>>>> instance Jsonb will populate fields. Thought adapter should return a
>>>>> populated instance otherwise no way to convert to business model properly
>>>>> IMO (if you don't have an explicit model you maybe don't want a setter or
>>>>> field to be used). That's why I was kind of blocked there.
>>>>>
>>>>>
>>>>>> If you want to polymorphically adapt each animal in a collection you
>>>>>> would have instead annotate Animal.class with @JsonbTypeAdapter, or pass an
>>>>>> instance of AnimalAdapter to JsonbConfig.
>>>>>>
>>>>>> You are right, you can't add @JsonbTypeAdapter(AnimalAdapter.class)
>>>>>> to List<Animal> as it would than have to be declared as: "extends
>>>>>> TypeAdapter<List<Animal>>" and parent implementation would not work than.
>>>>>>
>>>>>>
>>>>> Well adapter for items instead of the field in case of a collection is
>>>>> something we can implement - we do in Johnzon - and which is useful IMO.
>>>>> That said it doesn't solve the polymorphism issue. If [A] is solved it can
>>>>> work but today we don't have any way to know if the adapter builds the
>>>>> instance or just instantiate it if I got you right.
>>>>>
>>>>>
>>>>>> Did I get your point?
>>>>>>
>>>>>>
>>>>> Think so.
>>>>>
>>>>>
>>>>>> Roman.
>>>>>>
>>>>>>
>>>>>> On 03/23/2016 12:04 PM, Romain Manni-Bucau wrote:
>>>>>>
>>>>>> I don't get this part "Jsonb looks at animal field model and gets
>>>>>> "toType" from annotated adapter".
>>>>>>
>>>>>> How do you create a Dog in your example instead of an Animal.
>>>>>>
>>>>>> Keep in mind you don't know all types from jsonb point of view. The
>>>>>> real use case is more obvious on a collection - at least for me:
>>>>>>
>>>>>> public static class Pojo {
>>>>>> @JsonbTypeAdapter(AnimalAdapter.class)
>>>>>> public Collection<Animal> animals; // Dog, Cow, Cat, Horse...
>>>>>> }
>>>>>>
>>>>>>
>>>>>>
>>>>>> Romain Manni-Bucau
>>>>>> @rmannibucau
>>>>>> <http://www.tomitribe.com>http://www.tomitribe.com
>>>>>> <http://rmannibucau.wordpress.com>http://rmannibucau.wordpress.com
>>>>>> <https://github.com/rmannibucau>https://github.com/rmannibucau
>>>>>>
>>>>>> 2016-03-23 11:51 GMT+01:00 Roman Grigoriadi <
>>>>>> <roman.grigoriadi_at_oracle.com>roman.grigoriadi_at_oracle.com>:
>>>>>>
>>>>>>> You don't instantiate X in adapter you already have it. Here is
>>>>>>> implementation of such adapter:
>>>>>>>
>>>>>>> class TypeAdapter<T> implements JsonbAdapter<T, TypeWrapper<T>> {
>>>>>>>
>>>>>>> @Override
>>>>>>> public TypeWrapper<T> adaptToJson(T obj) throws Exception {
>>>>>>> TypeWrapper<T> wrapper = new TypeWrapper<>();
>>>>>>> wrapper.setClassName(obj.getClass().getName());
>>>>>>> wrapper.setInstance(obj);
>>>>>>> return wrapper;
>>>>>>> }
>>>>>>>
>>>>>>> @Override
>>>>>>> public T adaptFromJson(TypeWrapper<T> obj) throws Exception {
>>>>>>> return obj.getInstance();
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> class AnimalAdapter extends TypeAdapter<Animal> {}
>>>>>>>
>>>>>>> Than you have a pojo like this:
>>>>>>>
>>>>>>> public static class Pojo {
>>>>>>> @JsonbTypeAdapter(AnimalAdapter.class)
>>>>>>> public Animal animal;
>>>>>>> }
>>>>>>>
>>>>>>> And json like this:
>>>>>>>
>>>>>>> {
>>>>>>> "animal":{"className":"com.foo.Dog",name":"Doggie","dogProperty":"Property of a Dog."}}
>>>>>>> }
>>>>>>>
>>>>>>>
>>>>>>> What happens during deserialization in our implementation is:
>>>>>>> JsonParser generates an event for started object at "animal" property.
>>>>>>> Jsonb looks at animal field model and gets "toType" from annotated adapter.
>>>>>>> Deserialization than happens for TypedWrapper as for common arbitrary user
>>>>>>> Type, but with custom deserializer, reading class property first and
>>>>>>> creating instance from it. After TypedWrapper<Animal> is fully
>>>>>>> deserialized, it is passed to adapter instance, to retrieve an Animal,
>>>>>>> which is finally set to Animal field.
>>>>>>>
>>>>>>> Regards,
>>>>>>> Roman
>>>>>>>
>>>>>>>
>>>>>>> On 03/23/2016 11:20 AM, Romain Manni-Bucau wrote:
>>>>>>>
>>>>>>> Hi Roman,
>>>>>>>
>>>>>>> can you fill some "..." please? typically at the moment "I know the
>>>>>>> type is X". How with an adapter do you instantiate X and then let jsonb
>>>>>>> populate it (without having another Jsonb instance)? That was the main
>>>>>>> missing part of the puzzle.
>>>>>>>
>>>>>>>
>>>>>>> Romain Manni-Bucau
>>>>>>> @rmannibucau
>>>>>>> <http://www.tomitribe.com>http://www.tomitribe.com
>>>>>>> <http://rmannibucau.wordpress.com>http://rmannibucau.wordpress.com
>>>>>>> <https://github.com/rmannibucau>https://github.com/rmannibucau
>>>>>>>
>>>>>>> 2016-03-23 11:14 GMT+01:00 Roman Grigoriadi <
>>>>>>> <roman.grigoriadi_at_oracle.com>roman.grigoriadi_at_oracle.com>:
>>>>>>>
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> @Romain - what you and Dmitry suggested with adapters, will actully
>>>>>>>> work in our case. We will have to to add a custom deserializer handler for
>>>>>>>> a "TypedWrapper<T>" (similar to collection / array or reflection
>>>>>>>> deserializers), which will read a class property first and on
>>>>>>>> encountering a json object for T will create a correct type instance. The
>>>>>>>> only condition would be, that class property must appear before inner
>>>>>>>> instance in json object for "TypedWrapper<T>" as Eugen suggested:
>>>>>>>>
>>>>>>>> {"classProperty":"com.foo.Dog","instance":{...}}
>>>>>>>>
>>>>>>>> Adapters will than work in a common way to extract T from
>>>>>>>> TypedWrapper and set it to a class model be it a field or a
>>>>>>>> collection/array.
>>>>>>>>
>>>>>>>> I would also add required enumeration of allowed subtypes into
>>>>>>>> TypedAdapter:
>>>>>>>>
>>>>>>>> class TypedAdapter<T> implements JsonbAdapter<T, TypedWrapper<T>> {
>>>>>>>> TypedAdapter(Class[] allowedSubtypes) {...}
>>>>>>>> ...
>>>>>>>> }
>>>>>>>>
>>>>>>>> So we don't allow loading of any arbitrary class suggested by
>>>>>>>> incoming json in case of not trusted third party.
>>>>>>>>
>>>>>>>> @Romain - adding support for custom serializers / deserializers in
>>>>>>>> fashion of fasterxml with access to JsonGenerator/JsonParser would also
>>>>>>>> solve the problem in similar fashion, but it would be more complicated for
>>>>>>>> a client to implement logic driven by JsonParser events, than by providing
>>>>>>>> predefined adapter.
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Roman
>>>>>>>>
>>>>>>>> On 03/21/2016 09:36 PM, Romain Manni-Bucau wrote:
>>>>>>>>
>>>>>>>> Hi Dmitry,
>>>>>>>>
>>>>>>>> was my thought as well but it doesn't really work cause in adapter
>>>>>>>> you can't relaunch the deserialization chain with the same jsonb instance.
>>>>>>>> The serialization side is the easy one but the deserialization makes
>>>>>>>> adapters API not enough to have a consistent behavior accross the
>>>>>>>> deserialization. Making the adapter "JsonbAware" would work. We can
>>>>>>>> probably use @Inject (CDI if there or just the JSR 330 as an optional
>>>>>>>> dependency if not)
>>>>>>>>
>>>>>>>> Side note: I'd like we enable this impl but we don't provide them
>>>>>>>> in the spec since it is likely dependent on your use case and saw cases
>>>>>>>> where type was not enough and we will likely not handle all possible models.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Romain Manni-Bucau
>>>>>>>> @rmannibucau
>>>>>>>> <http://www.tomitribe.com>http://www.tomitribe.com
>>>>>>>> <http://rmannibucau.wordpress.com>http://rmannibucau.wordpress.com
>>>>>>>> <https://github.com/rmannibucau>https://github.com/rmannibucau
>>>>>>>>
>>>>>>>> 2016-03-21 21:27 GMT+01:00 Dmitry Kornilov <
>>>>>>>> <dmitry.kornilov_at_oracle.com>dmitry.kornilov_at_oracle.com>:
>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> This topic has been discussed already. Current version of the spec
>>>>>>>>> is clear about polymorphism: *“**Deserialization into polymorphic
>>>>>>>>> types is not supported by default mapping. [JSB-3.8-1]”. *The
>>>>>>>>> spec is almost finished and I am strongly against going back and changing
>>>>>>>>> some basic things now.
>>>>>>>>>
>>>>>>>>> On the other hand I understand that this use case exists. There is
>>>>>>>>> a possible workaround to it using adapters. Sorry if there are any
>>>>>>>>> mistakes, I am writing code without checking.
>>>>>>>>>
>>>>>>>>> We can create a generic wrapper to any type holding its type info
>>>>>>>>> like this:
>>>>>>>>>
>>>>>>>>> class TypedWrapper<T> {
>>>>>>>>> String type;
>>>>>>>>> T obj;
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> We can create a generic adapter which converts type to wrapper and
>>>>>>>>> vice versa. I am not putting a full implementation here, I hope that the
>>>>>>>>> idea is clear:
>>>>>>>>>
>>>>>>>>> class TypedAdapter implements JsonbAdapter<T, TypedWrapper<T>> {
>>>>>>>>> TypedWrapper adaptToJson(T obj) {
>>>>>>>>> TypedWrapper<T> t = new TypedWrapper<T>();
>>>>>>>>> t.type = obj.getClass().getName();
>>>>>>>>> t.obj = obj;
>>>>>>>>> return t;
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> T adaptFromJson(TypedWrapper<T> t) {
>>>>>>>>> // Use reflection API to create an instance of object
>>>>>>>>> based on t.type field value
>>>>>>>>> }
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> Now lets imagine that we have the following classes:
>>>>>>>>>
>>>>>>>>> class Animal {
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> class Dog extends Animal {
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> class Cat extends Animal {
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> class Foo {
>>>>>>>>> Animal animal;
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> To properly handle serialization/deserialization of Foo we just
>>>>>>>>> need to create an adapter which extends TypedAdapter from ab
>>>>>>>>>
>>>>>>>> ...
>>
>>
>>
>
>