users@jsonb-spec.java.net

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

From: Roman Grigoriadi <roman.grigoriadi_at_oracle.com>
Date: Thu, 31 Mar 2016 17:35:31 +0200

Ok you are right with the provider.. Your proposal looks good..

The problem is - I don't have any out of the box functionality in
jsonb-ri to convert an arbitrary object to JsonObject and back. This
what I thought user can do himself in the adapter. If we implement such
a generic conversion internally in jsonb-ri than yes, looks it will work
this way.

Roman

On 03/31/2016 04:58 PM, Romain Manni-Bucau wrote:
> 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 <mailto: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 BoxToJsonObjectAdapterimplements 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 BoxToJsonObjectAdapterimplements 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 <mailto: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
>>> <mailto: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 Stringname; }
>>>
>>> public static class Dogextends Animal {
>>> public StringdogProperty; }
>>>
>>> public static class Catextends Animal {
>>> public StringcatProperty; }
>>>
>>> public static class Pojo {
>>> public Animalanimal; 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
>>>> <mailto: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
>>>>> <mailto: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
>>>>>> <mailto: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://rmannibucau.wordpress.com
>>>>>>> https://github.com/rmannibucau
>>>>>>>
>>>>>>> 2016-03-23 11:51 GMT+01:00 Roman
>>>>>>> Grigoriadi <roman.grigoriadi_at_oracle.com
>>>>>>> <mailto: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://rmannibucau.wordpress.com
>>>>>>>> https://github.com/rmannibucau
>>>>>>>>
>>>>>>>> 2016-03-23 11:14 GMT+01:00 Roman
>>>>>>>> Grigoriadi
>>>>>>>> <roman.grigoriadi_at_oracle.com
>>>>>>>> <mailto: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://rmannibucau.wordpress.com
>>>>>>>>> https://github.com/rmannibucau
>>>>>>>>>
>>>>>>>>> 2016-03-21 21:27 GMT+01:00
>>>>>>>>> Dmitry Kornilov
>>>>>>>>> <dmitry.kornilov_at_oracle.com
>>>>>>>>> <mailto: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
>>>>>>>>>
>>> ...
>>>
>>
>>
>
>