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