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 <mailto: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?
> - 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?
> - 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?
>
> 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 <mailto: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
>>> <mailto: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 JsonbGeneratorextends 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 JsonbParserextends 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 CrateSerializerimplements 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 CrateDeserializerimplements 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
>>>
>>>
>>
>>
>
>