jsr367-experts@jsonb-spec.java.net

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

From: Romain Manni-Bucau <rmannibucau_at_tomitribe.com>
Date: Mon, 21 Mar 2016 10:37:35 +0100

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