jsr367-experts@jsonb-spec.java.net

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

From: Romain Manni-Bucau <rmannibucau_at_tomitribe.com>
Date: Mon, 9 May 2016 19:48:05 +0200

2016-05-09 19:37 GMT+02:00 Eugen Cepoi <cepoi.eugen_at_gmail.com>:

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


> 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.
>>
>
Think the topic was more about keeping an object view at user level or not.
Relying on jsonp for feature as a default never have been under discussion
AFAIK.


> 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.
>>
>
Issue there is how to distinguish between list serialization and plain
object serialization. This can be needed to not modify all object
structures in some cases. I'm also happy with a context having a flag for
that purpose.


> 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
>>>>>> >> >>>>>>>>>>>
>>>>>> >> >>>>>>>>>>
>>>>>> >> >>>>>>>>>
>>>>>> >> >>>>>>>>
>>>>>> >> >>>>>>>
>>>>>> >> >>>>>>
>>>>>> >> >>>>>
>>>>>> >> >>>>
>>>>>> >> >>>
>>>>>> >> >>
>>>>>> >> >
>>>>>> >
>>>>>> >
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>
>>
>