users@jsonb-spec.java.net

[jsonb-spec users] [jsr367-experts] Re: Re: Re: Re: Re: Re: JSONB De/Serializers proposal

From: Eugen Cepoi <cepoi.eugen_at_gmail.com>
Date: Mon, 9 May 2016 10:37:47 -0700

Oh and I think that the type in the deserialize methods should be the first
parameter.

2016-05-09 10:35 GMT-07:00 Eugen Cepoi <cepoi.eugen_at_gmail.com>:

> Some quick feedback over the different proposed solutions:
>
> 1/ Dependency on Jsonp sounds relatively OK and makes the stack more
> consistent. I understand the point about performance or "unnecessary
> indirection" but I think this would be fine. Redoing another layer of
> parsing/writing in Jsonb would be worse IMO.
> 2/ There can be several uses having a context that holds state. But in
> practice I found that this is mostly useful to just delegate back the
> ser/de.
> 3/ I am against having methods to serialize object vs lists, this
> information is available in the type. The name should be written/consumed
> by the current serializer and the delegation should act only on the value.
> 4/ The convert can be seen as a nice feature but to implement it more
> efficiently than a round trip it requires some work, that is a bit annoying.
>
> Cheers,
> Eugen
>
> 2016-05-09 8:30 GMT-07:00 Romain Manni-Bucau <rmannibucau_at_tomitribe.com>:
>
>>
>> 2016-05-09 16:57 GMT+02:00 Dmitry Kornilov <dmitry.kornilov_at_oracle.com>:
>>
>>> Hi,
>>>
>>> Romain finally posted some code! Good news! ;)
>>>
>>> > 1. doesnt prevent impl not jsonp based (genson got some optimization
>>> incompatible with jsonp IIRC),
>>>
>>> The point is that JSONB uses JSONP based parser and not designed to use
>>> parser other than JSONP. It will perfectly work with third party parser
>>> implementing JSONP interface. I personally not a big fan of JSONP,
>>> especially the way it is developing now. But it’s a standard and it’s right
>>> to use it.
>>>
>>> > 2. why should the user potentially mess up or suppose anything about
>>> jsonp there?
>>>
>>> Serialiser/Deserializer is a low level API. These interfaces we use
>>> internally for the same reasons. We are using JSONP parser. It would be
>>> fair to give it directly to users.
>>>
>>
>> An implementation can choose to rely on jsonp and JsonReader instead of
>> JsonParser and it would work too so - and there is a small overlap with 1.
>> - why going that deep there and just not assuming the need of our own API
>> in jsonb (providing jsonp there we delegate the responsability of our own
>> API to another spec which is fine when it does the same but jsonb has this
>> mapping thing - no real order on user land - making the streaming not
>> matching the user expectation very well in term of API).
>>
>> What if a user eats more than the "current" object? -> exception? Should
>> it even be allowed?
>> What if a user needs to try a field? -> we fail if we don't provide a
>> jsonb wrapper able to mark/browse the current object
>> -> this use case if the following "In v1 we had "marker": string but
>> in v2 we have "marker":{"foo":"bar"}. It can sound insane and irreal but it
>> is actually common and keeping in mind json comes maybe not from java it is
>> even more obvious (angular2 beta -> rc just did this kind of trick to its
>> users).
>>
>> In short: think we can't be lazy and avoid to hide jsonp there. However
>> we can reduce the amount of methods (we don't need a method for
>> byte|long|BigNumber|... but we only need a single one by kind of method
>> since typing is already handled in jsonb runtime)
>>
>>
>>>
>>> > Main issue I have there is in SerializationContext and list handling
>>> where "key" will be the list key and not the instance one. We can of course
>>> add another method for arrays or pass a "context”
>>> > to give the information (SerializationTreeContext = {array =
>>> [true|false], key = [string]} and we remove the key from the signature).
>>>
>>> I agree with this one. We need to add a method to SerialisationContext
>>> which serialises an object without a key (array element).
>>>
>>>
>> Note: not sure you noticed but I removed convert method from my snippet,
>> for me jsonb can ensure it is used as configured and it doesnt loop (guess
>> risk was stackoverflow? or was it just cause we were @jsonp level so we
>> needed to add back jsonb one?)
>>
>> Last note: think we should add to the context the propertyNamingStrategy
>> to keep to the user the java view. This way he can convert a java name to a
>> json name (use case: reusable (de)serializers/framework (de)serializers). I
>> would just put a getter in contexts.
>>
>>
>>
>>
>>> Thanks,
>>> Dmitry
>>>
>>>
>>> On 09 May 2016, at 08:40, Romain Manni-Bucau <rmannibucau_at_tomitribe.com>
>>> wrote:
>>>
>>> Hi Dmitry,
>>>
>>> I would really prefer a lighter version without jsonp references then:
>>> https://gist.github.com/rmannibucau/66907a09c1f062b378e67c7f511425c0 .
>>> Note: I tried to comment a bit big changes with "RMB" notes.
>>>
>>> Main issue I have there is in SerializationContext and list handling
>>> where "key" will be the list key and not the instance one. We can of course
>>> add another method for arrays or pass a "context" to give the information
>>> (SerializationTreeContext = {array = [true|false], key = [string]} and we
>>> remove the key from the signature).
>>>
>>>
>>>
>>> Romain Manni-Bucau
>>> @rmannibucau
>>> http://www.tomitribe.com
>>> http://rmannibucau.wordpress.com
>>> https://github.com/rmannibucau
>>>
>>> 2016-05-08 21:59 GMT+02:00 Dmitry Kornilov <dmitry.kornilov_at_oracle.com>:
>>>
>>>> Hi,
>>>>
>>>> Here is a final rework.
>>>>
>>>>
>>>> 1. We decided to be consistent with other frameworks and reverted
>>>> back to a version with serialization/deserialization contexts. All JSON
>>>> binding framewords now use a similar solution.
>>>> 2. If we declare integration with Jsonp we need to use its
>>>> parser/generator interfaces instead of Jsonb wrappers. It also simplifies
>>>> the API.
>>>>
>>>>
>>>> Please take a look. If there is no (or not many) negative comments I
>>>> will consider it as a final version.
>>>>
>>>> Dmitry, Roman
>>>>
>>>> public interface JsonbSerializer<T> {
>>>>
>>>> /**
>>>> * Serializes an object to JSON.
>>>> *
>>>> * @param obj object to serialize
>>>> * @param generator JSON generator to use
>>>> * @param ctx JSONB mapper context
>>>> */
>>>> void serialize(T obj, JsonGenerator generator, SerializationContext
>>>> ctx);
>>>> }
>>>>
>>>> public interface JsonbDeserializer<T> {
>>>>
>>>> /**
>>>> * Deserialize an object from JSON.
>>>> * Cursor of JsonParser is at START_OBJECT.
>>>> *
>>>> * @param parser Json parser
>>>> * @param ctx Deserialization context
>>>> * @param rtType type of returned object
>>>> * @return deserialized instance
>>>> */
>>>> T deserialize(JsonParser parser, DeserializationContext ctx, Type
>>>> rtType);
>>>> }
>>>>
>>>> public interface SerializationContext {
>>>>
>>>> /**
>>>> * Serializes arbitrary object to JSON, using current {_at_link
>>>> javax.json.stream.JsonGenerator} instance.
>>>> *
>>>> * @param key JSON key name
>>>> * @param object object to serialize
>>>> * @param generator JSONP generator to serialize with
>>>> * @param <T> Type of serialized object
>>>> */
>>>> <T> void serialize(String key, T object, JsonGenerator generator);
>>>>
>>>> /**
>>>> * Converts string value into provided type. String value has to be
>>>> single JSON value, not a part
>>>> * of a JSON document representing JSON object.
>>>> *
>>>> * @param obj object to convert to string
>>>> * @param generator JSONP generator to serialize with
>>>> * @param <T> type of object
>>>> *
>>>> * @return converted string value
>>>> * @throws javax.json.bind.JsonbException if conversion of given
>>>> type is not supported
>>>> */
>>>> <T> String convertDefault(T obj, JsonGenerator generator);
>>>> }
>>>>
>>>> ublic interface DeserializationContext {
>>>>
>>>> /**
>>>> * Deserializes JSON stream into instance of provided class using
>>>> {_at_link javax.json.stream.JsonParser}.
>>>> * JsonParser cursor have to be at KEY_NAME before START_OBJECT to
>>>> call this method.
>>>> *
>>>> * @param clazz Type to deserialize into. No arg constructor
>>>> required.
>>>> * @param parser JSONP parser to drive
>>>> * @param <T> Type of class
>>>> * @return Deserialized instance
>>>> */
>>>> <T> T deserialize(Class<T> clazz, JsonParser parser);
>>>>
>>>> /**
>>>> * Deserializes JSON stream into instance of provided class using
>>>> {_at_link javax.json.stream.JsonParser}.
>>>> * JsonParser cursor have to be at KEY_NAME before START_OBJECT to
>>>> call this method.
>>>> *
>>>> * @param type Type to deserialize into. No arg constructor
>>>> required.
>>>> * @param parser JSONP parser to drive
>>>> * @param <T> Type to deserialize into
>>>> * @return Deserialized instance
>>>> */
>>>> <T> T deserialize(Type type, JsonParser parser);
>>>>
>>>> /**
>>>> * Converts string value into provided type. String value has to be
>>>> single JSON value, not a part
>>>> * of a JSON document representing JSON object.
>>>> *
>>>> * @param clazz Class to convert string value into
>>>> * @param value single JSON value to convert
>>>> * @param <T> type of toClass
>>>> * @return converted instance
>>>> * @throws javax.json.bind.JsonbException if conversion of provided
>>>> type is not supported
>>>> */
>>>> <T> T convertDefault(Class<T> clazz, String value);
>>>>
>>>> }
>>>>
>>>>
>>>> On 02 May 2016, at 16:31, Romain Manni-Bucau <rmannibucau_at_tomitribe.com>
>>>> wrote:
>>>>
>>>> Yes, like more but still few things (sorry):
>>>>
>>>> Write side:
>>>> - writeObject(T) would be valid since we have a contextual key too and
>>>> would act as an adapter more or less. writeObject(String, T) would be for a
>>>> sub object then.
>>>> - do we need writeArray - I think so but case is limit enough to be
>>>> ignored.
>>>> - comment says "void writeInt(String key, int value);",: would like we
>>>> return JsonbWriter to keep the API fluent, is that possible?
>>>>
>>>> Read side:
>>>> - more or less the same: I think we need for symmetry getObject(String,
>>>> type)
>>>> - [semantic and consistency with jsonp] if we really want to keep
>>>> parser constraints (which are technically valid) maybe we should just go
>>>> with JsonbParser instead of reader (and ignore previous point)?
>>>>
>>>> Sounds close for me! :)
>>>>
>>>>
>>>>
>>>> Romain Manni-Bucau
>>>> @rmannibucau
>>>> http://www.tomitribe.com
>>>> http://rmannibucau.wordpress.com
>>>> https://github.com/rmannibucau
>>>>
>>>> 2016-05-02 16:17 GMT+02:00 Dmitry Kornilov <dmitry.kornilov_at_oracle.com>
>>>> :
>>>>
>>>>> Hi,
>>>>>
>>>>> Here is a new version of API.
>>>>>
>>>>> 1. We removed XXXContext classes and moved some methods from there to
>>>>> JsonbReader/Writer classes.
>>>>> 2. JsonObject is not a main citizen now. (Romain should be happy :) )
>>>>>
>>>>> Take a look. Tell us what you think.
>>>>>
>>>>> Cheers,
>>>>> Dmitry, Roman
>>>>>
>>>>> public interface JsonbSerializer<T> {
>>>>>
>>>>> /**
>>>>> * @param obj Object to process
>>>>> * @param writer Low level JSON writer
>>>>> * @param ctx Jsonb mapper
>>>>> */
>>>>> void serialize(T obj, JsonbWriter writer);
>>>>>
>>>>> }
>>>>>
>>>>> public interface JsonbDeserializer<T> {
>>>>>
>>>>> /**
>>>>> * @param parser Low level JSON reader
>>>>> * @param ctx Jsonb mapper
>>>>> * @param rtType Runtime type of T
>>>>> */
>>>>> T deserialize(JsonbReader reader, Type rtType);
>>>>> }
>>>>>
>>>>>
>>>>> /**
>>>>> * Jsonb wrapper around JSONP generator + helper methods.
>>>>> */
>>>>> public interface JsonbWriter {
>>>>>
>>>>> // methods delegated from JSONP generator
>>>>> // void writeInt(String key, int value);
>>>>> // etc.
>>>>>
>>>>> /**
>>>>> * Serializes and writes a given object.
>>>>> */
>>>>> <T> void writeObject(String key, T obj);
>>>>> }
>>>>>
>>>>> /**
>>>>> * Jsonb wrapper around JSONP parser + helper methods.
>>>>> */
>>>>> public interface JsonbReader {
>>>>>
>>>>> // methods delegated from jsonp parser such as
>>>>> // long getLong();
>>>>> // boolean hasNext();
>>>>> // etc.
>>>>>
>>>>> /**
>>>>> * Deserializes JSON stream into instance of provided class with JSONB using {_at_link javax.json.stream.JsonParser}.
>>>>> * JsonParser cursor have to be at KEY_NAME before START_OBJECT to call this method.
>>>>> */
>>>>> <T> T getObject(Class<T> clazz);
>>>>>
>>>>> /**
>>>>> * Similar as above for generic types.
>>>>> */
>>>>> <T> T getObject(Type typeInfo);
>>>>> }
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On 29 Apr 2016, at 23:43, Romain Manni-Bucau <
>>>>> rmannibucau_at_tomitribe.com> wrote:
>>>>>
>>>>>
>>>>> Le 29 avr. 2016 20:20, "Roman Grigoriadi" <roman.grigoriadi_at_oracle.com>
>>>>> a écrit :
>>>>> >
>>>>> > Hi,
>>>>> >
>>>>> > 1. I am for a Type as a rtType parameter. It may be a parameterized
>>>>> type itself, you can get raw class from it, but you can't get type params
>>>>> if a static class will be passed.
>>>>> >
>>>>>
>>>>> Work to start - there are workarounds if needed.
>>>>>
>>>>> > 2. User will know if current event is start object or start array.
>>>>> But we can add it for convenience.
>>>>> >
>>>>> > 3. Did you mean methods, which are in (De)Serialization contexts?
>>>>> <T> void serialize(String key, T object); and <T> T
>>>>> deserialize(Class<T>/Type clazz);?
>>>>> >
>>>>>
>>>>> Yes. More I think more I see context as a state holder - which part of
>>>>> the graph i am in - than a writer/reader. Can just be a semantic issue.
>>>>> What do others think?
>>>>>
>>>>> > 4. Actually if type is supported or not will not change during
>>>>> runtime. User should know from the spec / vendor doc if conversion for a
>>>>> given type is supported. We can throw exception if it is not supported or
>>>>> return result as Optional.
>>>>>
>>>>> Just thought it was more fluent but will not be that sad if tou think
>>>>> it was not a good idea.
>>>>>
>>>>> >
>>>>> > Roman
>>>>> >
>>>>> >
>>>>> > On 04/29/2016 03:28 PM, Romain Manni-Bucau wrote:
>>>>> >>
>>>>> >>
>>>>> >> Le 29 avr. 2016 15:03, "Dmitry Kornilov" <
>>>>> dmitry.kornilov_at_oracle.com> a écrit :
>>>>> >> >
>>>>> >> >
>>>>> >> > 1.
>>>>> >> >
>>>>> >> > Imagine that we have a serialiser defined as this:
>>>>> >> >
>>>>> >> > JsonbDeserializer<Animal>
>>>>> >> >
>>>>> >> > There is a generic Dog class extending Animal interface:
>>>>> >> > Dog<T> extends Animal
>>>>> >> >
>>>>> >> > And the actual object that we are deserialising is:
>>>>> >> > Dog<WhatEver>
>>>>> >> >
>>>>> >> > ParametrizedType representing Dog<WhatEver> type will be passed
>>>>> as rtType parameter. I suppose it’s runtime type, not static.
>>>>> >> >
>>>>> >>
>>>>> >> You can get Object for generic converters so static type would be
>>>>> better in such a case.
>>>>> >>
>>>>> >> > 2.
>>>>> >> >
>>>>> >> > I am not sure. Maybe we need it. Roman, please answer.
>>>>> >> >
>>>>> >> > 3.
>>>>> >> >
>>>>> >> > I didn’t understand what are you talking about. The best would be
>>>>> if you modify our API code from the previous email so we can better
>>>>> understand what you mean.
>>>>> >> >
>>>>> >>
>>>>> >> Basically bring back Jsonb API for a subobject us the idea.
>>>>> readObject(Type) typically or readObject(Type, attribute). Idea is to use
>>>>> Object instead of JsonXXX everywhere as first class citizen. We can provide
>>>>> an unwrap(JsonXxx) if user wants to go lower level bit i dont see it useful
>>>>> yet.
>>>>> >>
>>>>> >> > 4.
>>>>> >> >
>>>>> >> > We don’t use optional constraints in our code. We are sort of old
>>>>> school, you know. :)
>>>>> >> > But the idea is reasonable. Let us discuss it.
>>>>> >> >
>>>>> >> > Thanks,
>>>>> >> > Dmitry
>>>>> >> >
>>>>> >> >
>>>>> >> >> On 29 Apr 2016, at 13:07, Romain Manni-Bucau <
>>>>> rmannibucau_at_tomitribe.com> wrote:
>>>>> >> >>
>>>>> >> >> Hi Roman,
>>>>> >> >>
>>>>> >> >> looks better, few comments:
>>>>> >> >>
>>>>> >> >> 1- @param rtType Runtime type of T think it should be static
>>>>> type more than runtime no?
>>>>> >> >> 2- do we want readStructure(Type)?
>>>>> >> >> 3- more generally we should get mapped versions of
>>>>> [read|write][Object|Array|Structure] (readObject(Type) typically) otherwise
>>>>> we kind of loose the mapping level jsonb should be at, no?
>>>>> >> >> 4- [open question] do we go with optional for convertion and get
>>>>> rid of supports method: convert(.../*supported case*/).orElse(..../* not
>>>>> supported */)
>>>>> >> >>
>>>>> >> >> Main point is 3, once solved I think we are good.
>>>>> >> >>
>>>>> >> >>
>>>>> >> >> Romain Manni-Bucau
>>>>> >> >> @rmannibucau
>>>>> >> >> http://www.tomitribe.com
>>>>> >> >> http://rmannibucau.wordpress.com
>>>>> >> >> https://github.com/rmannibucau
>>>>> >> >>
>>>>> >> >> 2016-04-29 12:23 GMT+02:00 Dmitry Kornilov <
>>>>> dmitry.kornilov_at_oracle.com>:
>>>>> >> >>>
>>>>> >> >>> Hi,
>>>>> >> >>>
>>>>> >> >>> Romain, thanks for your suggestions. Below you can find a fixed
>>>>> version of serialisers API. What’s changed:
>>>>> >> >>>
>>>>> >> >>> JsonbGenerator/JsonbParser renamed to JsonbWriter/JsonbReader.
>>>>> >> >>> JsonbWriter and JsonbReader are not extended from the
>>>>> corresponding JSONP classes as Romain suggested.
>>>>> >> >>> Some JSON processing methods added to JsonbWriter and
>>>>> JsonbReader. Possible we will need to add some more. Your suggestions?
>>>>> >> >>> Introduced rtType parameter in JsonbDeserializer.deserialize
>>>>> method. It holds a runtime type of an object.
>>>>> >> >>>
>>>>> >> >>> WDYT?
>>>>> >> >>>
>>>>> >> >>> Dmitry, Roman
>>>>> >> >>>
>>>>> >> >>>
>>>>> >> >>> public interface JsonbSerializer<T> {
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * @param obj Object to process
>>>>> >> >>> * @param writer Low level JSON writer
>>>>> >> >>> * @param ctx Jsonb mapper
>>>>> >> >>> */
>>>>> >> >>> void serialize(T obj, JsonbWriter writer,
>>>>> SerializationContext ctx);
>>>>> >> >>>
>>>>> >> >>> }
>>>>> >> >>>
>>>>> >> >>> public interface JsonbDeserializer<T> {
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * @param parser Low level JSON reader
>>>>> >> >>> * @param ctx Jsonb mapper
>>>>> >> >>> * @param rtType Runtime type of T
>>>>> >> >>> */
>>>>> >> >>> T deserialize(JsonbReader reader, DeserializationContext
>>>>> ctx, Type rtType);
>>>>> >> >>> }
>>>>> >> >>>
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Jsonb wrapper around JSONP generator + helper methods.
>>>>> >> >>> */
>>>>> >> >>> public interface JsonbWriter {
>>>>> >> >>>
>>>>> >> >>> // methods delegated from JSONP generator
>>>>> >> >>> // ...
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Writes a JSONP object.
>>>>> >> >>> */
>>>>> >> >>> void writeObject(javax.json.JsonObject obj);
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Writes a JSONP array.
>>>>> >> >>> */
>>>>> >> >>> void writeArray(javax.json.JsonArray arr);
>>>>> >> >>>
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Writes a JSONP object.
>>>>> >> >>> */
>>>>> >> >>> void writeStructure(javax.json.JsonStructure struct);
>>>>> >> >>> }
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Jsonb wrapper around JSONP parser + helper methods.
>>>>> >> >>> */
>>>>> >> >>> public interface JsonbReader {
>>>>> >> >>>
>>>>> >> >>> // methods delegated from jsonp parser
>>>>> >> >>> // ...
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Reads a JSONP object.
>>>>> >> >>> */
>>>>> >> >>> javax.json.JsonObject readObject();
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Reads a JSONP array.
>>>>> >> >>> */
>>>>> >> >>> javax.json.JsonArray readArray();
>>>>> >> >>> }
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Jsonb mapper used for serialization.
>>>>> >> >>> */
>>>>> >> >>> public interface SerializationContext {
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Serializes arbitrary object to JSON with JSONB, using
>>>>> current {_at_link javax.json.stream.JsonGenerator} instance.
>>>>> >> >>> */
>>>>> >> >>> <T> void serialize(String key, T object);
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Checks if type is supported for conversion to string by
>>>>> JSONB.
>>>>> >> >>> */
>>>>> >> >>> boolean supportsConversion(Class<?> clazz);
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Converts string value into provided type. String value
>>>>> has to be single JSON value, not a part
>>>>> >> >>> * of a JSON document representing JSON object / array.
>>>>> >> >>> */
>>>>> >> >>> <T> String convertDefault(T obj);
>>>>> >> >>> }
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Jsonb deserialization mapper.
>>>>> >> >>> */
>>>>> >> >>> public interface DeserializationContext {
>>>>> >> >>> /**
>>>>> >> >>> * Deserializes JSON stream into instance of provided class
>>>>> with JSONB using {_at_link javax.json.stream.JsonParser}.
>>>>> >> >>> * JsonParser cursor have to be at KEY_NAME before
>>>>> START_OBJECT to call this method.
>>>>> >> >>> */
>>>>> >> >>> <T> T deserialize(Class<T> clazz);
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Similar as above for generic types.
>>>>> >> >>> */
>>>>> >> >>> <T> T deserialize(TypeInfo<T> typeInfo);
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Checks if type is supported for conversion from string
>>>>> by JSONB.
>>>>> >> >>> */
>>>>> >> >>> boolean supportsConversion(Class<?> toClass);
>>>>> >> >>>
>>>>> >> >>> /**
>>>>> >> >>> * Converts string value into provided type. String value
>>>>> has to be single JSON value, not a part
>>>>> >> >>> * of a JSON document representing JSON object.
>>>>> >> >>> */
>>>>> >> >>> <T> T convertDefault(Class<T> toClass, String value);
>>>>> >> >>>
>>>>> >> >>> }
>>>>> >> >>>
>>>>> >> >>>
>>>>> >> >>>
>>>>> >> >>>
>>>>> >> >>>> On 28 Apr 2016, at 16:43, Romain Manni-Bucau <
>>>>> rmannibucau_at_tomitribe.com> wrote:
>>>>> >> >>>>
>>>>> >> >>>>
>>>>> >> >>>> 2016-04-28 16:09 GMT+02:00 Roman Grigoriadi <
>>>>> roman.grigoriadi_at_oracle.com>:
>>>>> >> >>>>>
>>>>> >> >>>>> Inline, thanks, Roman
>>>>> >> >>>>>
>>>>> >> >>>>> On 04/28/2016 03:31 PM, Romain Manni-Bucau wrote:
>>>>> >> >>>>>>
>>>>> >> >>>>>>
>>>>> >> >>>>>> 2016-04-28 15:26 GMT+02:00 Roman Grigoriadi <
>>>>> roman.grigoriadi_at_oracle.com>:
>>>>> >> >>>>>>>
>>>>> >> >>>>>>> Thought main reason for (de)seserializers is to provide
>>>>> such a low level API to drive the JSONP by hand. The drawback is that user
>>>>> must use Parser/Generator judiciously, because it is shared with JSONB
>>>>> runtime. If we hide it completely, what methods would JsonbXXX interfaces
>>>>> have? You cant do anything like getValue(String key), because once parser
>>>>> is advanced it cannot move back. How about dropping JsonbXXX completly and
>>>>> using JSONP Generator / Parser along with (De)SerializationContexts?
>>>>> >> >>>>>>>
>>>>> >> >>>>>>
>>>>> >> >>>>>> Well that's one of the reason why we shouldn't expose jsonp.
>>>>> So here what I had in mind:
>>>>> >> >>>>>> - expose all method of jsonp but in Jsonb API
>>>>> >> >>>>>
>>>>> >> >>>>> How does hiding JSONP and providing 1:1 JSONB interface help
>>>>> against biasing runtime with inconsistently advanced parser? What are other
>>>>> pitfalls if we expose JSONP in deserializers?
>>>>> >> >>>>
>>>>> >> >>>>
>>>>> >> >>>> As a user you see the json structure not the stream so having
>>>>> a parser is an implementation detail you don't need (you need a reader more
>>>>> than a parser to be honest). Then up to the jsonb runtime to bufferise what
>>>>> needs to be bufferised to keep its parser up to date.
>>>>> >> >>>>
>>>>> >> >>>> The other pitfalls I see is to not be able to present a
>>>>> consistent view to the users and open the unsafe usage with next jsonp
>>>>> releases (if you use jsonp N+1 with jsonb N generations).
>>>>> >> >>>>
>>>>> >> >>>>>
>>>>> >> >>>>>
>>>>> >> >>>>>> - the Jsonb impl is free to use markable parser (able to
>>>>> rewind/forward if needed) to make user happy whatever he does
>>>>> >> >>>>>
>>>>> >> >>>>> Is it? What about custom JSONP Providers in JsonbConfig?
>>>>> Aren't implementations supposed to use only JSONP API as their backend?
>>>>> >> >>>>
>>>>> >> >>>>
>>>>> >> >>>> Didn't follow. Maybe my comment was unclear: the markable impl
>>>>> would be an internal of jsonb runtime.
>>>>> >> >>>>
>>>>> >> >>>>>
>>>>> >> >>>>>
>>>>> >> >>>>>> - Jsonb versions should get object/array handling in
>>>>> addition
>>>>> >> >>>>>>>
>>>>> >> >>>>>>> so deserializer method may look like:
>>>>> >> >>>>>>>
>>>>> >> >>>>>>> T deserialize(JsonParser parser, //JSONP parser
>>>>> >> >>>>>>> DeserializationContext context)
>>>>> //has JSONB mapper related methods
>>>>> >> >>>>>>>
>>>>> >> >>>>>>> or
>>>>> >> >>>>>>>
>>>>> >> >>>>>>> T deserialize(DeserializationContext context)
>>>>> >> >>>>>>> and add
>>>>> >> >>>>>>> JsonParser DeserializationContext#getParser() ?
>>>>> >> >>>>>>>
>>>>> >> >>>>>>> According to generics part, did you mean that you would not
>>>>> be able to resolve X if Deserializer is defined as
>>>>> MyDeserializer<MyPojo<X>> and you want JSONB to pass a type of X into
>>>>> deserializer? So that deserialize(...) method would be added by argument
>>>>> Type typeOfX ?
>>>>> >> >>>>>>>
>>>>> >> >>>>>>
>>>>> >> >>>>>> If I got it right yes. (De)Serializer can be generic and
>>>>> loose the type at instantiation (or not even have it if in a framework
>>>>> where new MYDeser<X>(){} wouldnt work). So the minimum the runtime can do
>>>>> is to say "hey, this is the best type I can find for what you have to
>>>>> return".
>>>>> >> >>>>>
>>>>> >> >>>>> It didn't make much sense to me to declare a serializer in
>>>>> such way. If you declare it like "class <T> MyDeser<MyPojo<T>> you still
>>>>> have to provide some T during instantiation (will be erased). If T is
>>>>> declared in a class, which creates instance of a serializer, how will JSONB
>>>>> know what is it bound to in runtime?
>>>>> >> >>>>>
>>>>> >> >>>>
>>>>> >> >>>> You have the model and know you need to get an Animal for
>>>>> instance. Then if it is an interface it will likely not work and the
>>>>> deserializer will need to take the impl from somewhere else but at least as
>>>>> a runtime you did your best and you would work in most of cases.
>>>>> >> >>>>
>>>>> >> >>>>>>
>>>>> >> >>>>>>
>>>>> >> >>>>>>>
>>>>> >> >>>>>>> Thanks,
>>>>> >> >>>>>>> Roman
>>>>> >> >>>>>>>
>>>>> >> >>>>>>>
>>>>> >> >>>>>>> On 04/27/2016 03:16 PM, Romain Manni-Bucau wrote:
>>>>> >> >>>>>>>>
>>>>> >> >>>>>>>> 2016-04-27 15:12 GMT+02:00 Roman Grigoriadi <
>>>>> roman.grigoriadi_at_oracle.com>:
>>>>> >> >>>>>>>>>
>>>>> >> >>>>>>>>> The difference between JsonbXXX and (De)SerContext is
>>>>> separation of processing logic, former has methods for driving JSONP,
>>>>> latter uses JSONB on top of it.
>>>>> >> >>>>>>>>>
>>>>> >> >>>>>>>>
>>>>> >> >>>>>>>> I get it but the main purpose of the mapper if IMO to hide
>>>>> the parsing part so I would keep it but not as a main concept. That said
>>>>> I'm ok with that if I'm alone on this side ;).
>>>>> >> >>>>>>>>
>>>>> >> >>>>>>>>>
>>>>> >> >>>>>>>>> I don't get whats wrong with runtime type, for
>>>>> serialization. Have you noticed
>>>>> >> >>>>>>>>>
>>>>> >> >>>>>>>>> <T> T deserialize(TypeInfo<T> typeInfo);
>>>>> >> >>>>>>>>>
>>>>> >> >>>>>>>>> method? It will deserialize generic types.
>>>>> >> >>>>>>>>>
>>>>> >> >>>>>>>>
>>>>> >> >>>>>>>> Sure but how do you do a new X() if you don't know X()? so
>>>>> the deserialize should get the static type somehow. <T> T deserialize() is
>>>>> an option but guess having the type in the signature allows to not
>>>>> instantiate it if not needed.
>>>>> >> >>>>>>>>
>>>>> >> >>>>>>>>>
>>>>> >> >>>>>>>>> Roman.
>>>>> >> >>>>>>>>>
>>>>> >> >>>>>>>>>
>>>>> >> >>>>>>>>> On 04/27/2016 02:43 PM, Romain Manni-Bucau wrote:
>>>>> >> >>>>>>>>>>
>>>>> >> >>>>>>>>>> Hi Roman,
>>>>> >> >>>>>>>>>>
>>>>> >> >>>>>>>>>> Few points but globally I think we move in the right
>>>>> direction!
>>>>> >> >>>>>>>>>>
>>>>> >> >>>>>>>>>> - "extends JsonXXX" I'd replace the extends by a
>>>>> delegation to keep the fluent API typed (= return type is JsonbXXX and not
>>>>> JsonXXX) and control over jsonb API.
>>>>> >> >>>>>>>>>> - I don't fully get the difference between context and
>>>>> JsonbXXX, i'd merge them (otherwise we would just using jsonp API but as
>>>>> mentionned in previous point it has the drawback to loose all the control.
>>>>> >> >>>>>>>>>> - deserialization: we still need the type found by the
>>>>> runtime (reflection) otherwise we can't allow generic serializers at all
>>>>> >> >>>>>>>>>>
>>>>> >> >>>>>>>>>>
>>>>> >> >>>>>>>>>>
>>>>> >> >>>>>>>>>> Romain Manni-Bucau
>>>>> >> >>>>>>>>>> @rmannibucau
>>>>> >> >>>>>>>>>> http://www.tomitribe.com
>>>>> >> >>>>>>>>>> http://rmannibucau.wordpress.com
>>>>> >> >>>>>>>>>> https://github.com/rmannibucau
>>>>> >> >>>>>>>>>>
>>>>> >> >>>>>>>>>> 2016-04-27 14:33 GMT+02:00 Roman Grigoriadi <
>>>>> roman.grigoriadi_at_oracle.com>:
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> Hi experts,
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> following previous discussions for including
>>>>> de/serializers in JSONB along with adapters, here is proposal for
>>>>> interfaces in JSONB API:
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> public interface JsonbSerializer<T> {
>>>>> >> >>>>>>>>>>> void serialize(T obj, JsonbGenerator generator,
>>>>> SerializationContext ctx);
>>>>> >> >>>>>>>>>>> }
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> public interface JsonbDeserializer<T> {
>>>>> >> >>>>>>>>>>> T deserialize(JsonbParser parser,
>>>>> DeserializationContext ctx);
>>>>> >> >>>>>>>>>>> }
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> /**
>>>>> >> >>>>>>>>>>> * Jsonb decorator for JSONP generator. Includes
>>>>> validation for writing END_OBJECT / END_ARRAY checking level of closed JSON
>>>>> structure.
>>>>> >> >>>>>>>>>>> * Helper generator methods may be added here.
>>>>> >> >>>>>>>>>>> */
>>>>> >> >>>>>>>>>>> public interface JsonbGenerator extends JsonGenerator {
>>>>> >> >>>>>>>>>>> }/**
>>>>> >> >>>>>>>>>>> * Jsonb decorator for JSONP parser. Includes
>>>>> validation of cursor position after leaving deserializer, alters hasNext()
>>>>> behavior.
>>>>> >> >>>>>>>>>>> * Helper parser methods may be added here.
>>>>> >> >>>>>>>>>>> */
>>>>> >> >>>>>>>>>>> public interface JsonbParser extends JsonParser {
>>>>> >> >>>>>>>>>>> }
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> public interface SerializationContext {
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> /**
>>>>> >> >>>>>>>>>>> * Serializes arbitrary object to JSON with JSONB,
>>>>> using current {_at_link javax.json.stream.JsonGenerator} instance.
>>>>> >> >>>>>>>>>>> */
>>>>> >> >>>>>>>>>>> <T> void serialize(String key, T object);
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> /**
>>>>> >> >>>>>>>>>>> * Checks if type is supported for conversion to
>>>>> string by JSONB.
>>>>> >> >>>>>>>>>>> */
>>>>> >> >>>>>>>>>>> boolean supportsConversion(Class<?> clazz);
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> /**
>>>>> >> >>>>>>>>>>> * Converts string value into provided type. String
>>>>> value has to be single JSON value, not a part
>>>>> >> >>>>>>>>>>> * of a JSON document representing JSON object /
>>>>> array.
>>>>> >> >>>>>>>>>>> */
>>>>> >> >>>>>>>>>>> <T> String convertDefault(T obj);
>>>>> >> >>>>>>>>>>> }public interface DeserializationContext {
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> /**
>>>>> >> >>>>>>>>>>> * Deserializes JSON stream into instance of
>>>>> provided class with JSONB using {_at_link javax.json.stream.JsonParser}.
>>>>> >> >>>>>>>>>>> * JsonParser cursor have to be at KEY_NAME before
>>>>> START_OBJECT to call this method.
>>>>> >> >>>>>>>>>>> */
>>>>> >> >>>>>>>>>>> <T> T deserialize(Class<T> clazz);
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> /**
>>>>> >> >>>>>>>>>>> * Similar as above for generic types.
>>>>> >> >>>>>>>>>>> */
>>>>> >> >>>>>>>>>>> <T> T deserialize(TypeInfo<T> typeInfo);
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> /**
>>>>> >> >>>>>>>>>>> * Checks if type is supported for conversion from
>>>>> string by JSONB.
>>>>> >> >>>>>>>>>>> */
>>>>> >> >>>>>>>>>>> boolean supportsConversion(Class<?> toClass);
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> /**
>>>>> >> >>>>>>>>>>> * Converts string value into provided type. String
>>>>> value has to be single JSON value, not a part
>>>>> >> >>>>>>>>>>> * of a JSON document representing JSON object.
>>>>> >> >>>>>>>>>>> */
>>>>> >> >>>>>>>>>>> <T> T convertDefault(Class<T> toClass, String
>>>>> value);
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> }
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> JsonbParser / JsonbGenerator objects are supposed to
>>>>> decorate JSONP behavior.
>>>>> >> >>>>>>>>>>> For example in case of JsonParser hasNext() call may be
>>>>> altered to return false if currently deserialized object has ended in the
>>>>> stream. Helper methods (like nextKey(String), isKey(String), etc for json
>>>>> processing may be included here.
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> In addition to Generators/Parsers,
>>>>> (De)SerializationContexts are intended to provide JSONB functionality such
>>>>> as (de)serialization of arbitrary java types, conversion to/from string of
>>>>> known types such are Dates or Numbers.
>>>>> >> >>>>>>>>>>> We could also add some insight into introspected
>>>>> customization from JSONB annotations based on a Class and property name.
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> An example of how implementation of such (de)serializer
>>>>> may look:
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> public class CrateSerializer implements
>>>>> JsonbSerializer<Crate> {
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> @Override
>>>>> >> >>>>>>>>>>> public void serialize(Crate obj, JsonbGenerator
>>>>> generator, SerializationContext ctx) {
>>>>> >> >>>>>>>>>>> generator.write("crateStr", "REPLACED");
>>>>> >> >>>>>>>>>>> ctx.serialize("crateInner", obj.crateInner);
>>>>> >> >>>>>>>>>>> ctx.serialize("crateInnerList",
>>>>> obj.crateInnerList);
>>>>> >> >>>>>>>>>>> generator.write("date-converted", dateValue);
>>>>> >> >>>>>>>>>>> }
>>>>> >> >>>>>>>>>>> }
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> public class CrateDeserializer implements
>>>>> JsonbDeserializer<Crate> {
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> @Override
>>>>> >> >>>>>>>>>>> public Crate deserialize(JsonbParser jsonParser,
>>>>> DeserializationContext ctx) {
>>>>> >> >>>>>>>>>>> Crate crate = new Crate();
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> while (jsonParser.hasNext()) {
>>>>> >> >>>>>>>>>>> JsonParser.Event next = jsonParser.next();
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> if (next.equals(JsonParser.Event.KEY_NAME)
>>>>> && jsonParser.getString().equals("crateInner")) {
>>>>> >> >>>>>>>>>>> //invokes JSONB processing for a
>>>>> CrateInner as a root type with "shared" instance of JsonParser
>>>>> >> >>>>>>>>>>> //may invoke other serializer or
>>>>> adapter instances inside
>>>>> >> >>>>>>>>>>> crate.crateInner =
>>>>> ctx.deserialize(CrateInner.class);
>>>>> >> >>>>>>>>>>> next = jsonParser.next();
>>>>> >> >>>>>>>>>>> }
>>>>> >> >>>>>>>>>>> if (next.equals(JsonParser.Event.KEY_NAME)
>>>>> && jsonParser.getString().equals("crateInnerList")) {
>>>>> >> >>>>>>>>>>> //invokes JSONB processing for a
>>>>> List<CrateInner> as a root type with "shared" instance of JsonParser
>>>>> >> >>>>>>>>>>> //may invoke other serializer or
>>>>> adapter instances inside
>>>>> >> >>>>>>>>>>> crate.crateInnerList =
>>>>> ctx.deserialize(new TypeToken<List<CrateInner>>() {});
>>>>> >> >>>>>>>>>>> }
>>>>> >> >>>>>>>>>>> if (next.equals(JsonParser.Event.KEY_NAME) &&
>>>>> jsonParser.getString().equals("date-converted")) {
>>>>> >> >>>>>>>>>>> jsonParser.next();
>>>>> >> >>>>>>>>>>> //don't have context of processing
>>>>> here, no annotation customizations applied.
>>>>> >> >>>>>>>>>>> Date converted =
>>>>> ctx.convertDefault(Date.class, jsonParser.getString());
>>>>> >> >>>>>>>>>>> crate.date = converted;
>>>>> >> >>>>>>>>>>> }
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> }
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> return crate;
>>>>> >> >>>>>>>>>>> }
>>>>> >> >>>>>>>>>>> }
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> @Romain, this is similar to what you have suggested
>>>>> first time.
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> In addition JsonbAdapters may be used to convert From /
>>>>> To JsonObject or JsonArray, but auto conversion between unknown JavaTypes
>>>>> and JsonStructure will not be supported, at least in first version of a
>>>>> spec.
>>>>> >> >>>>>>>>>>> WDYT?
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>> Thanks,
>>>>> >> >>>>>>>>>>> Roman
>>>>> >> >>>>>>>>>>>
>>>>> >> >>>>>>>>>>
>>>>> >> >>>>>>>>>
>>>>> >> >>>>>>>>
>>>>> >> >>>>>>>
>>>>> >> >>>>>>
>>>>> >> >>>>>
>>>>> >> >>>>
>>>>> >> >>>
>>>>> >> >>
>>>>> >> >
>>>>> >
>>>>> >
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>
>>>
>>
>