users@jsonb-spec.java.net

[jsonb-spec users] [jsr367-experts] Re: Re: Re: Re: [17-Customizing names]

From: Martin Vojtek <voytoo_at_gmail.com>
Date: Wed, 13 May 2015 14:53:10 +0200

On Wed, May 13, 2015 at 1:34 PM, Eugen Cepoi <cepoi.eugen_at_gmail.com> wrote:

>
>
> 2015-05-13 8:40 GMT+02:00 Martin Vojtek <voytoo_at_gmail.com>:
>
>> Hi Experts,
>>
>> we should get some conclusion to this discussion.
>>
>> I have the following notes:
>>
>> 1. Nillable, JsonbProperty, JsonbTransient
>>
>> I don't see any problem adding nillable attribute to JsonbProperty
>> annotation. The situation with JsonbTransient is different, because
>> transient field is effectively not a JsonbProperty. I think JsonbTransient
>> should stay as is.
>>
>>
> Adding target Property to JsonbProperty makes sense.
>>
>> 2. Property Naming
>>
>
>> I see concept of Mappers equivalent to JsonbAdapter (analogy to
>> XmlAdapter). It means that JsonbAdapter should see the context to be able
>> to do complex mapping between type and JSON fragment.
>>
>
> What is the context to you? From memory there is no context in XmlAdapter.
> Also I think it could make sense to allow users to register Adapters
> directly to JsonB (using the builder or config) vs only via annotations.
>
>

Right now I don't know exactly what information JsonbAdapter needs, but the
idea behind context is that JsonbAdapter should be able to override as much
as possible behavior of default mapping. One option is to give access to
JsonbConfig. It allows to change behavior when some property is set. The
other option is to have access to information what has already been
processed. For example if there is dependency between objects in JSON.
Another interesting option is possibility to skip some part of json, or to
change some behavior during processing of the JSON. But maybe there should
be no context and to keep the concept of JsonbAdapter simple in version 1.0.


>
>> Composition of Mappings looks like an advanced feature and maybe it
>> should be postponed to future spec version.
>>
>
> By composition of mappings do you think of allowing users to provide an
> Adapter/Mapper for some type that uses another registered adapters/mappers?
>
> For example I provide an PersonsAdapter<List<Person>> but inside I don't
> want to deal with the mapping of each entry and want to delegate to the
> default adapter of person.
>
>
>> WDYT?
>>
>> 3. Property Order
>>
>> Case insensitive mapping is special, because it is not 1:1 mapping. To
>> make PropertyOrderStrategy simple, it should support only 1:1 mapping. In
>> that case PropertyOrderPolicy should not implement PropertyOrderStrategy. I
>> am not sure if there is a need to introduce Accessor class. In this case
>> simple String -> String mapping (accessor name -> JSON key) should work.
>> Implementations could provide some internal mechanism to call this function
>> only once per property.
>>
>
> I guess you are talking about naming and mean PropertyNamingStrategy and
> PropertyNamingPolicy.
>
> You are right, I was thining about different things at once and at the end
I have messed it into one point ...


> Even if I like the names "strategy" and "policy" (who doesn't, this sounds
> pretty cool :)) I find them confusing when used together.
> I think both mean the same thing :)
>
>
I'm not that good in inventing names :) If you have better names, it is
still possible to change that.


> To me there are two things with some common parts:
> - Resolve names (using Java Bean convetion/Annotations/Other)
> - Translate the string to another string
> (lower/upper/dashed/underscore/blabla)
>
>
+1


> The first one could deal directly with "properties" where the second one
> takes the resolved name and translates it.
> So here we have the choice of:
> - Have two separate concepts. One interface PropertyNameResolver that
> deals with properties or some abstraction. And a
> PropertyNamingStrategy/Policy interface that takes a string and returns
> another string (and provides the default impls as static attributes of the
> interface).
> - Or we consider that the name resolution is relatively fixed and
> handled inside the spec impl, thus we expose only the naming
> strategy/policy. Though I think this too is probably even more fixed...
> - Or we expose only the name resolution API
>
> No matter the choice, I'd be for providing default impls for all those
> inside the spec. There aren't many ways to implement a name resolution from
> java bean or annotations, neither to translate camel case to underscore...
>
>

Agree with default impls + two separate concepts.


>
>> +1 for changing getPropertiesOrder to something immutable like
>> Collection/Iterable parameter.
>>
>> 4. JsonPointer support
>>
>> @JsonbProperty({"foo", "bar"}) vs @JsonbProperty("/foo/bar")
>>
>> This should be discussed in separate thread.
>>
>> 5. Null serialization policy
>>
>> Replacing enum with JsonbConfig options makes sense. User should be able
>> to implement custom null serialization policy for given type with the use
>> of JsonbAdapter (not proposed yet).
>>
>
> I think it is nice to allow the users to not care about handling null
> input (when implementing their Adapter) and do it inside the spec. In this
> situation they would need a way to express "hey don't handle nulls for me"
> - or the inverse "please deal with nulls for me".
>
>
It would be nice, but it could possibly complicate the contract and there
could be a lot of things (which can depend on each other) to specify.


> Eugen
>
>
>>
>> MartinV
>>
>> On Wed, Apr 29, 2015 at 10:35 PM, Eugen Cepoi <cepoi.eugen_at_gmail.com>
>> wrote:
>>
>>>
>>>
>>> 2015-04-29 22:18 GMT+02:00 Romain MB <rmannibucau_at_tomitribe.com>:
>>>
>>>> 2015-04-29 21:54 GMT+02:00 Eugen Cepoi <cepoi.eugen_at_gmail.com>:
>>>> > I think JsonbProperty should accept Parameter as target. This would
>>>> allow to
>>>> > use it on constructor parameters (and factory methods).
>>>> >
>>>> > About all the naming policy, I agre with Romain. We should have an
>>>> interface
>>>> > that defines the naming strategy api (convert from one string to
>>>> another or
>>>> > from a Method/Field/Param to a String) and provide impls as an enum
>>>> for the
>>>> > actual policies.
>>>> >
>>>> > I don't think NullSerPolicy is useful. IMO it should be an option at
>>>> the
>>>> > builder or jsonbconfig level and provide some way to the user to
>>>> implement a
>>>> > custom strategy (so a kind of Adapter/Converter/Whatever where he has
>>>> enough
>>>> > information to decide how he should ser/de).
>>>> >
>>>> > In PropertyOrderStrategy we give to the user control to a mutable
>>>> structure
>>>> > the array of strings, perhaps we should provide just a
>>>> collection/iterable
>>>> > or document that the user can or not modify the original structure.
>>>> Also I
>>>> > am not sure there is enough information to sort things properly. For
>>>> example
>>>> > the user doesn't know from which class the property comes (ex: A
>>>> extends B,
>>>> > does it come from A or B).
>>>> >
>>>>
>>>> That is why a mapping API (class -> Map<String /* json key */,
>>>> Accessor> map(Class)) is nice but I agree it is less user friendly
>>>> since it mixed 3 concerns (naming, merging and accessibility). We can
>>>> of course provide helpers but not sure it is a good idea for a v1.0 of
>>>> the API.
>>>>
>>>
>>> Mhh I don't like mixing so much things :)
>>>
>>> I don't know if its "the best" way, but in Genson I have one mechanism
>>> for selecting if a property (method/field/param) should be used in ser/de
>>> and another one that resolves the name (this is a bit different than a
>>> naming strategy where one would translate a string into another one). This
>>> allows one to choose what the name should be based on infos like
>>> annotations, declaring class, type etc. This is done per "property".
>>>
>>> Something similar doesn't prevent then having a "renaming" strategy that
>>> would take a string (without any other infos) and transform it to another
>>> string.
>>>
>>> The merging stuff is a bit more buried in the internal api as I didn't
>>> think people would need easy control over this.
>>>
>>>
>>>>
>>>> > About Nillable, I don't care :) But following the same logic, what
>>>> about
>>>> > JsonTransient?
>>>> >
>>>>
>>>> +1 for transient (as annotation or field of property one depending
>>>> what we decide here) is important to fully ignore a field.
>>>>
>>>> > For JsonPointer, Path & cie, jsonp will come with an impl of
>>>> jsonpointer
>>>> > over the DOM model. This could make things easier... Also what's the
>>>> > advantage of @JsonbProperty({"foo", "bar"}) vs
>>>> @JsonbProperty("/foo/bar") ?
>>>> > The sad thing is that I think we can't express something like:
>>>> >
>>>>
>>>> or even foo.bar? just the fact you can use all "single string" naming
>>>> as key and not path:
>>>>
>>>
>>> Oh I didn't think about this. Naturally I would feel more comfortable to
>>> define a path "foo/bar" vs {"foo", "bar"}, but I don't have enough insight
>>> into this kind of usage to have a solid opinion :)
>>>
>>> Side note: I have been hesitant to add something similar in genson for
>>> some time, but initially I wanted to provide stuff that worked over streams
>>> and not DOM. In practice this gets tricky to implement (even more if you
>>> want to support immutable objects) and not flexible (once the stream has
>>> been consumed you can't extract properties from it anymore). So in the end
>>> relying on what has been done in jsonp could be more pragmatic...
>>>
>>>
>>>>
>>>> { // Map
>>>> "/home/rmannibucau/Desktop": "5MB",
>>>> "/home/rmannibucau/dev": "65MB"
>>>> }
>>>>
>>>> which is valid to map to:
>>>>
>>>> public class MyFiles {
>>>> @JsonbProperty("/home/rmannibucau/Desktop")
>>>> private String desktop;
>>>>
>>>> @JsonbProperty("/home/rmannibucau/dev")
>>>> private String dev;
>>>> }
>>>>
>>>>
>>>> > @JsonProperty("/person/childrens/name")
>>>> > List<String> childrenNames;
>>>> >
>>>> > where the json would be
>>>> > {
>>>> > person {
>>>> > childrens: [ {...name: foo}, {...name: bar} ]
>>>> > }
>>>> > }
>>>> >
>>>> >
>>>> > I agree with Romain about the composition part. This can be pretty
>>>> neat, not
>>>> > only for naming but also for property resolution.
>>>> >
>>>> >
>>>> > 2015-04-29 21:08 GMT+02:00 Romain MB <rmannibucau_at_tomitribe.com>:
>>>> >>
>>>> >>
>>>> >> Le 29 avr. 2015 19:18, "Martin Vojtek" <voytoo_at_gmail.com> a écrit :
>>>> >> >
>>>> >> >
>>>> >> >
>>>> >> > On Wed, Apr 29, 2015 at 6:56 PM, Romain MB <
>>>> rmannibucau_at_tomitribe.com>
>>>> >> > wrote:
>>>> >> >>
>>>> >> >> 2015-04-29 18:30 GMT+02:00 Martin Vojtek <voytoo_at_gmail.com>:
>>>> >> >> > Hi,
>>>> >> >> >
>>>> >> >> > ad 1) interface for PropertyNamingPolicy?
>>>> >> >> >
>>>> >> >> > I was experimenting with the idea of interface, but there is an
>>>> open
>>>> >> >> > question how to design API to provide support also for the
>>>> reverse
>>>> >> >> > mapping.
>>>> >> >> >
>>>> >> >> > For example, if I have case insensitive mapping, I need to know
>>>> how
>>>> >> >> > to map
>>>> >> >> > from JSON key to field name (in efficient way). I have removed
>>>> such
>>>> >> >> > an
>>>> >> >> > interface to see if there is a need for such customization
>>>> (obviously
>>>> >> >> > there
>>>> >> >> > is :)).
>>>> >> >> >
>>>> >> >> > The alternative is to provide mechanism analogical to
>>>> JAXBAdapter
>>>> >> >> > mechanism
>>>> >> >> > (or general mapper for given type).
>>>> >> >> >
>>>> >> >>
>>>> >> >> think we can do better than something called each time here. Why
>>>> not
>>>> >> >> just a Mapper? String map(Accessor)?
>>>> >> >>
>>>> >> >
>>>> >> > this is mapping from Accessor to JSON. This works in many cases
>>>> (like
>>>> >> > 1:1), but what about other cases like case insensitive special
>>>> case?
>>>> >> >
>>>> >>
>>>> >> I would expect to be able to compose them in my code:
>>>> >>
>>>> >> new MyMapping(DefaultMappings.LEXICOGRAPHIC,
>>>> >> DefaultMappings.CASE_INSENSITIVE);
>>>> >>
>>>> >> The impl being just a chain in this case but could also managed an
>>>> exclude
>>>> >> list to skip JPA state fields for instance - these fields are not in
>>>> user
>>>> >> code so cant be ignored by static code (annotations).
>>>> >>
>>>> >> > If we agree that this is enough and the special case will be
>>>> handled by
>>>> >> > JsonbAdapter, that it is ok.
>>>> >> >
>>>> >> >
>>>> >> >>
>>>> >> >> > ad 2)
>>>> >> >> >
>>>> >> >> > The difference between JsonbNillable and JsonbProperty is also
>>>> in
>>>> >> >> > scope. It
>>>> >> >> > makes sense to make JsonbNillable property to be available for
>>>> >> >> > Type/Package
>>>> >> >> > target.
>>>> >> >> >
>>>> >> >>
>>>> >> >> Makes sense but i would still add it in property and keep
>>>> @Nillable
>>>> >> >> for type and packages only.
>>>> >> >>
>>>> >> >
>>>> >> > Don't have strong opinion about this. What others think?
>>>> >> >
>>>> >> >
>>>> >> >>
>>>> >> >> > ad 3)
>>>> >> >> >
>>>> >> >> > Maybe it makes sense to make it more general. What about JSON
>>>> >> >> > Pointer?
>>>> >> >> >
>>>> >> >>
>>>> >> >> can make sense but should stay simple/fluent cause it is super
>>>> common
>>>> >> >> (github/confluence/...). If you have some pseudo code we can
>>>> discuss
>>>> >> >> around I would be more than happy to dig into it.
>>>> >> >>
>>>> >> >
>>>> >> > I was thinking about similar functionality as MOXy XPath provides.
>>>> >> >
>>>> >> > https://wiki.eclipse.org/EclipseLink/Examples/MOXy/XPath
>>>> >> >
>>>> >> > JSON-B could support reasonable subset of JSON Pointer to map field
>>>> >> > (JavaBean property) to given node.
>>>> >> >
>>>> >>
>>>> >> Let s try it. Maybe needs its own thread then.
>>>> >>
>>>> >> >>
>>>> >> >> > ad ProertyOrderStrategy with enum)
>>>> >> >> >
>>>> >> >> > no problem to introduce enum. In that case I would also add
>>>> >> >> > LEXICOGRAPHICAL,
>>>> >> >> > which is default (and slightly different than ALPHABETICAL).
>>>> >> >> >
>>>> >> >> > MartinV
>>>> >> >> >
>>>> >> >> >
>>>> >> >> > On Wed, Apr 29, 2015 at 6:09 PM, Romain MB
>>>> >> >> > <rmannibucau_at_tomitribe.com>
>>>> >> >> > wrote:
>>>> >> >> >>
>>>> >> >> >> Hi
>>>> >> >> >>
>>>> >> >> >> @JsonbProperty is good to rename a property.
>>>> >> >> >>
>>>> >> >> >> However I don't like much PropertyNamingPolicy being an enum.
>>>> How do
>>>> >> >> >> I
>>>> >> >> >> do if I want to prefix everything with "mysuperapp_"? I would
>>>> use an
>>>> >> >> >> interface instead with default implementations (as constants in
>>>> >> >> >> Jsonb
>>>> >> >> >> or in a DefaultPropertyNamingPolicies enum if you want). This
>>>> would
>>>> >> >> >> also be consistent with PropertyOrderStrategy (why not having
>>>> an
>>>> >> >> >> enum
>>>> >> >> >> with ALPHABETICAL, REFLECTION, REVERSE...)
>>>> >> >> >>
>>>> >> >> >> I think having nillable as an attribute of @JsonProperty is
>>>> maybe
>>>> >> >> >> better.
>>>> >> >> >>
>>>> >> >> >> Now the harder question. Suppose I have this json:
>>>> >> >> >>
>>>> >> >> >> {
>>>> >> >> >> "foo": {
>>>> >> >> >> "bar": "dummy"
>>>> >> >> >> }
>>>> >> >> >> }
>>>> >> >> >>
>>>> >> >> >> Can I map foo/bar to a field directly? I'm super tempted to
>>>> support
>>>> >> >> >> it. It means @JsonbProperty needs an array of string instead a
>>>> >> >> >> simple
>>>> >> >> >> String:
>>>> >> >> >>
>>>> >> >> >> public class MyBinding {
>>>> >> >> >> @JsonbProperty({ "foo", "bar" })
>>>> >> >> >> private String bar;
>>>> >> >> >> }
>>>> >> >> >>
>>>> >> >> >> Side note: of course this doesn't prevent simple renaming with
>>>> the
>>>> >> >> >> same user API as today (speaking about the "look") thanks to
>>>> >> >> >> annotations properties:
>>>> >> >> >>
>>>> >> >> >> public class MyBinding {
>>>> >> >> >> @JsonbProperty("foo")
>>>> >> >> >> private Foo _foo;
>>>> >> >> >> }
>>>> >> >> >>
>>>> >> >> >> trying to summarize my feedback, here are the points I'd like
>>>> to
>>>> >> >> >> discuss:
>>>> >> >> >>
>>>> >> >> >> 1) interface for PropertyNamingPolicy?
>>>> >> >> >> 2) nillable in @JsonbProperty (means value() would have an
>>>> empty
>>>> >> >> >> default to keep a nice API in all cases)
>>>> >> >> >> 3) nested attribute support?
>>>> >> >> >>
>>>> >> >> >>
>>>> >> >> >> Romain Manni-Bucau
>>>> >> >> >> @rmannibucau
>>>> >> >> >> http://www.tomitribe.com
>>>> >> >> >> http://rmannibucau.wordpress.com
>>>> >> >> >> https://github.com/rmannibucau
>>>> >> >> >>
>>>> >> >> >>
>>>> >> >> >> 2015-04-29 17:36 GMT+02:00 Martin Vojtek <voytoo_at_gmail.com>:
>>>> >> >> >> > Hi Experts,
>>>> >> >> >> >
>>>> >> >> >> > I have pushed proposal regarding Customizing names.
>>>> >> >> >> >
>>>> >> >> >> > Short summary:
>>>> >> >> >> >
>>>> >> >> >> > introduce annotation and enum with most common naming
>>>> policies.
>>>> >> >> >> >
>>>> >> >> >> > 1. use of javax.json.bind.annotation.JsonbProperty
>>>> >> >> >> > 2. using javax.json.bind.config.PropertyNamingPolicy
>>>> >> >> >> >
>>>> >> >> >> > JsonbProperty annotation is applicable to Field, getter or
>>>> setter.
>>>> >> >> >> >
>>>> >> >> >> > PropertyNamingPolicy enum contains several different
>>>> policies like
>>>> >> >> >> > IDENTITY,
>>>> >> >> >> > CASE_INSENSITIVE, LOWER_CASE_WITH_UNDERSCORE ...
>>>> >> >> >> >
>>>> >> >> >> > Details could be found in specification and in code (api +
>>>> >> >> >> > examples).
>>>> >> >> >> >
>>>> >> >> >> > MartinV
>>>> >> >> >> >
>>>> >> >> >> >
>>>> >> >> >
>>>> >> >> >
>>>> >> >
>>>> >> >
>>>> >
>>>> >
>>>>
>>>
>>>
>>
>