users@jsonb-spec.java.net

[jsonb-spec users] [jsr367-experts] Re: Re: Re: Polymorphic deserializer

From: Romain Manni-Bucau <rmannibucau_at_tomitribe.com>
Date: Tue, 10 May 2016 17:32:47 +0200

Yep, sorry if it was unclear, thought to draw a picture but not sure it
would have helped ;).


Romain Manni-Bucau
@rmannibucau
http://www.tomitribe.com
http://rmannibucau.wordpress.com
https://github.com/rmannibucau

2016-05-10 17:25 GMT+02:00 Roman Grigoriadi <roman.grigoriadi_at_oracle.com>:

> Ok, I think I finally got what you mean now. Deserializer reentrance is
> disabled only for the same type as current level type.
>
> Thank you,
> Roman
>
>
> On 05/10/2016 05:15 PM, Romain Manni-Bucau wrote:
>
> Why not my proposal of disabling it only for current level (ie same node
> of the tree when coming back)?
>
>
> Romain Manni-Bucau
> @rmannibucau
> http://www.tomitribe.com
> http://rmannibucau.wordpress.com
> https://github.com/rmannibucau
>
> 2016-05-10 17:04 GMT+02:00 Roman Grigoriadi <roman.grigoriadi_at_oracle.com>:
>
>> Yes, number of reentrances in deserializer depends on the model tree and
>> is finite. What bothers me is - if we disable reentrant calls to
>> deserializers by default, it will fail on the second level of recursive
>> model.
>>
>> On 05/10/2016 04:48 PM, Romain Manni-Bucau wrote:
>>
>> it shouldn't loop since it is not working on the same instance so at some
>> point you will stop (or you have a cycle which is something else but not
>> possible in plain JSON on deserialization - without references I mean).
>>
>>
>>
>> Romain Manni-Bucau
>> @rmannibucau
>> http://www.tomitribe.com
>> http://rmannibucau.wordpress.com
>> https://github.com/rmannibucau
>>
>> 2016-05-10 16:47 GMT+02:00 Roman Grigoriadi <
>> <roman.grigoriadi_at_oracle.com>roman.grigoriadi_at_oracle.com>:
>>
>>> But what if root is a part of deserialized subpart of the tree?
>>>
>>> class Part {
>>> ...
>>> List<Subpart>
>>> }
>>>
>>> class Subpart {
>>> ...
>>> Part child;
>>> }
>>>
>>> now in PartDeserializer you call ctx.deserialize( new
>>> TokenImpl<List<Subpart>>() {}.getRuntimeType()) ?
>>>
>>> On 05/10/2016 04:29 PM, Romain Manni-Bucau wrote:
>>>
>>> case I had in mind was when you only deserialize a subpart of the tree
>>> and not the root directly. At each level you can prevent to re-enter in the
>>> same deserializer but you can need it later in the tree.
>>>
>>>
>>> Romain Manni-Bucau
>>> @rmannibucau
>>> http://www.tomitribe.com
>>> http://rmannibucau.wordpress.com
>>> https://github.com/rmannibucau
>>>
>>> 2016-05-10 16:02 GMT+02:00 Roman Grigoriadi <
>>> <roman.grigoriadi_at_oracle.com>roman.grigoriadi_at_oracle.com>:
>>>
>>>> Is there a usecase where you actually may need reentrant deserialize()
>>>> calls, with recursive models?
>>>>
>>>> When you call context.deserialize() inside deserializer, even for other
>>>> type than deserializer return type, you may still encounter deserialization
>>>> into return type of deserializer inside.
>>>>
>>>> Roman
>>>>
>>>>
>>>> On 05/10/2016 03:49 PM, Romain Manni-Bucau wrote:
>>>>
>>>> Hi Roman,
>>>>
>>>> We encountered it in johnzon when Mark implemented it. We chose to just
>>>> prevent these loops since they can easily be detected at framework level
>>>> but not expose it to the end user.
>>>>
>>>> typically in your code it would be:
>>>>
>>>> ctx.deserialize(clazz, parser) { // pseudo code
>>>>
>>>> return this.deserialize(clazz, parser, <ignore PolymorphicDeserializer for root level *only*>);
>>>>
>>>> }
>>>>
>>>> Note: in this snippet it would be great to not require the hasNext to be called (ie if called ok but if not then deserialize can do it).
>>>>
>>>>
>>>>
>>>>
>>>> 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-05-10 15:42 GMT+02:00 Roman Grigoriadi <
>>>> <roman.grigoriadi_at_oracle.com>roman.grigoriadi_at_oracle.com>:
>>>>
>>>>> According to polymorphic deserialization, which was one of the
>>>>> usecases for deserializers, I encountered the fact, that if
>>>>> context.deserialize() is called inside the deserializer for the type that
>>>>> is the return type for that deserializer, jsonb runtime will try to use
>>>>> such deserializer again inside. Example:
>>>>>
>>>>> public class PolymorphicDeserializer implements JsonbDeserializer<Animal> {
>>>>> @Override public Animal deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) {
>>>>> Class<? extends Animal> clazz = null;
>>>>>
>>>>> while (parser.hasNext()) { //some code to get class, which will result to subclass of an Animal //... //following will cause adding PolymorphicDeserializer instance to call stack again, calling deserialize on it
>>>>> return ctx.deserialize(clazz, parser); //--- REENTRANT CALL---
>>>>> }
>>>>> throw new IllegalStateException("animal not found!");
>>>>> }
>>>>> }
>>>>>
>>>>> Looks like this is correct behaviour, JSONB runtime has deserializer
>>>>> registered for it. Without some kind of parameter flag it has no clue not
>>>>> to use it. How about adding default to true method "boolean isReentrant()"
>>>>> to JsonbDeserializer interface?
>>>>>
>>>>> Thanks,
>>>>> Roman
>>>>>
>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>
>