users@jsonb-spec.java.net

[jsonb-spec users] [jsr367-experts] Re: Fwd: Re: Java polymorphism support

From: Przemyslaw Bielicki <pbielicki_at_gmail.com>
Date: Mon, 21 Mar 2016 10:46:38 +0100

@Romain - it looks clean for me.

Not sure we need anything specific for serialization, but deserialization
looks good - thanks :)

On Mon, Mar 21, 2016 at 10:37 AM, Romain Manni-Bucau <
rmannibucau_at_tomitribe.com> wrote:

>
>
> 2016-03-21 10:28 GMT+01:00 Przemyslaw Bielicki <pbielicki_at_gmail.com>:
>
>> OK in this case we can replace Java FQCN with an enum which would be more
>> elegant.
>>
>>
> it is business dependent and probably on the "best practiseé side more
> than technical one, right?
>
>
>> Is there a specific need for using PropertyOrderStrategy.LEXICOGRAPHICAL?
>>
>>
> assertEquals() in test, nothing on the functional side
>
>
>> Anyway, I'm not convinced this is necessary - it's a very simple example,
>> yet quite complex solution.
>>
>>
> What would be the alternative/simple solution? I don't think we can
> handle all cases in the spec cause when another tool will come with the
> need of the app id in the wrapper we'll be stucked and not able to handle
> it - if not this one it will be at next one etc...
>
> The clean solution for me would be:
>
> public class TypedSerializer impl/extend ... {
> @Override
> public void serialize(final JsonbGenerator generator /* extends
> JsonGenerator? to addd writeObject(instance) and writeCollection(list) */,
> final JsonStructure structure) {
> ///
> }
> }
> public class TypedDeserializer impl/extend ... {
> @Override
> public Object deserialize(final JsonbReader reader /* extends JsonReader,
> same idea as JsonbGenerator */) {
> return reader.read("value", loadClass(reader.getAttribute("type"))/*wrapper
> type*/).unwrap();
> }
> }
>
> Hardcoding any model will likely badly evolves IMHO or will not be used on
> the long term. Adapters are great but not contextual which makes them
> useless for this case until we get the JsonObject.
>
>
>
> On Mon, Mar 21, 2016 at 10:16 AM, Romain Manni-Bucau <
>> rmannibucau_at_tomitribe.com> wrote:
>>
>>> The adapter idea was:
>>>
>>>
>>> @Test
>>> public void notYetPloymorphism() { // we run it since it checked list/item conversion
>>> final Bar bar = new Bar();
>>> bar.value = 11;
>>>
>>> final Bar2 bar2 = new Bar2();
>>> bar2.value = 21;
>>> bar2.value2 = 22;
>>>
>>> final Polymorphism foo = new Polymorphism();
>>> foo.bars = new ArrayList<>(asList(bar, bar2));
>>>
>>> final Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withPropertyOrderStrategy(PropertyOrderStrategy.LEXICOGRAPHICAL));
>>>
>>> final String toString = jsonb.toJson(foo);
>>> assertEquals("{\"bars\":[" +
>>> "{\"type\":\"org.apache.johnzon.jsonb.AdapterTest$Bar\",\"value\":{\"value\":11}}," +
>>> "{\"type\":\"org.apache.johnzon.jsonb.AdapterTest$Bar2\",\"value\":{\"value\":21,\"value2\":22}}]}", toString);
>>>
>>> final Polymorphism read = jsonb.fromJson(toString, Polymorphism.class);
>>> assertEquals(2, read.bars.size());
>>> assertEquals(11, read.bars.get(0).value);
>>> assertTrue(Bar.class == read.bars.get(0).getClass());
>>> assertEquals(21, read.bars.get(1).value);
>>> /* SPEC LACK for this solution: THIS NEEDS A "FACTORY" BASED ON JsonObject: <T> T create(JsonObject currentNode); // currentNode={type, value}
>>>
>>> assertTrue(Bar2.class == read.bars.get(1).getClass());
>>> assertEquals(22, Bar2.class.cast(read.bars.get(1)).value2);
>>> */
>>> }
>>>
>>> with the model/adapter:
>>>
>>>
>>>
>>> public static class Polymorphism {
>>> @JsonbTypeAdapter(PolyBarAdapter.class)
>>> public List<Bar> bars;
>>> }
>>>
>>>
>>> public static class TypeInstance {
>>> public String type;
>>> private Bar value;
>>>
>>> public Bar getValue() {
>>> return value;
>>> }
>>>
>>> public void setValue(final Bar value) {
>>> this.value = value;
>>> }
>>> }
>>>
>>>
>>> public static class Bar2 extends Bar {
>>> public int value2;
>>> }
>>>
>>> public static class Bar {
>>> public int value;
>>> }
>>>
>>> public static class PolyBarAdapter implements JsonbAdapter<Bar, TypeInstance> {
>>> @Override
>>> public Bar adaptToJson(final TypeInstance obj) throws Exception {
>>> return obj.value;
>>> }
>>>
>>> @Override
>>> public TypeInstance adaptFromJson(final Bar obj) throws Exception {
>>> final TypeInstance typeInstance = new TypeInstance();
>>> typeInstance.type = obj.getClass().getName();
>>> typeInstance.value = obj;
>>> return typeInstance;
>>> }
>>> }
>>>
>>>
>>>
>>> The serializer idea is really the jackson one replacing its
>>> JsonSerializer by a new jsonb API mixing jsonp and jsonb:
>>> http://wiki.fasterxml.com/JacksonHowToCustomDeserializers and
>>> http://wiki.fasterxml.com/JacksonHowToCustomSerializers
>>>
>>> let me know if anything is unclear
>>>
>>>
>>> Romain Manni-Bucau
>>> @rmannibucau
>>> http://www.tomitribe.com
>>> http://rmannibucau.wordpress.com
>>> https://github.com/rmannibucau
>>>
>>> 2016-03-21 8:32 GMT+01:00 Przemyslaw Bielicki <pbielicki_at_gmail.com>:
>>>
>>>> Hi,
>>>>
>>>> I'm not a fan of the original idea (and it's an euphemism). Remember
>>>> that JSONB is used to serialize/deserialize DTOs, not domain objects. You
>>>> should have an additional adapter layer to convert DTOs into application's
>>>> business model/domain objects and back.
>>>> Polymorphism is broken (yeah, it's another topic and more philosophic)
>>>> and I would discourage its application in DTO layer. If you have to, you
>>>> can use an enum to mark what's the target class (check JPA for additional
>>>> inspirations). "//javaType": "x.y.z" is really bad idea IMO - what if you
>>>> use the same JSON to communicate with applications developed in .net,
>>>> python, php, c++ at the same time? (yes, it happens). Would you define a
>>>> type for each platform?
>>>>
>>>> If you use DTOs in business layer, you're doing something wrong :)
>>>>
>>>> @Romain, your idea looks interesting, can you show and example or
>>>> deserialization process where polymorphism is involved?
>>>>
>>>> Cheers,
>>>> Przemyslaw
>>>>
>>>> On Sun, Mar 20, 2016 at 10:52 PM, Romain Manni-Bucau <
>>>> rmannibucau_at_tomitribe.com> wrote:
>>>>
>>>>> Hi guys
>>>>>
>>>>> Why not allowing adapters to wrap and unwrap instances but keep
>>>>> serializer mecanism. For serialization no issue but for deserialization we
>>>>> need to switch the deserialized type and then post process the instance -
>>>>> or do it automatically with an Unwrappable interface?
>>>>>
>>>>> Overall idea for this particular use case would be:
>>>>>
>>>>> X ----TypedWrapper(X)----> JSON
>>>>> JSON----TypedWrapper.class----> TypedWrapped ----unwrap----> X
>>>>>
>>>>> Parts in arrows are adapter/jsonb integration.
>>>>>
>>>>> An alternative is to provide to adapters the stream and jsonp
>>>>> instances to do it themself with probably a mapper reference to
>>>>> re(de)serialise an object directly.
>>>>>
>>>>> Wdyt?
>>>>> ---------- Message transféré ----------
>>>>> De : "Romain Manni-Bucau" <rmannibucau_at_tomitribe.com>
>>>>> Date : 19 mars 2016 21:49
>>>>> Objet : Re: [jsonb-spec users] Java polymorphism support
>>>>> À : <users_at_jsonb-spec.java.net>
>>>>> Cc :
>>>>>
>>>>> Hi Sebastian
>>>>>
>>>>> I am not fan of that - Mark knows ;) - and in particular now I'm sure
>>>>> we shouldnt do it: the 0-day vulnerability is still there and you open the
>>>>> door to the same issue or a complicated config adding this feature in
>>>>> something as generic as jsonb.
>>>>> Le 19 mars 2016 21:28, "Sebastian Daschner" <
>>>>> java_at_sebastian-daschner.de> a écrit :
>>>>>
>>>>>> Hi experts,
>>>>>>
>>>>>> I don't know whether this has been discussed in the mailing list
>>>>>> before
>>>>>> but a needed functionality would be to specify the Java type of
>>>>>> properties in the serialized JSON.
>>>>>>
>>>>>> As JSON doesn't standardize comments or other "attributes" (like XML
>>>>>> does) a "magic property" could be added.
>>>>>>
>>>>>> Please see the proposal (explored by Mark Struberg, Reinhard Sandtner
>>>>>> and myself) on my blog:
>>>>>>
>>>>>> https://blog.sebastian-daschner.com/entries/json_mapping_polymorphism_support
>>>>>>
>>>>>> WDYT?
>>>>>>
>>>>>>
>>>>>> Cheers,
>>>>>> Sebastian
>>>>>>
>>>>>>
>>>>
>>>
>>
>