users@jsonb-spec.java.net

[jsonb-spec users] Re: [jsr367-experts] Re: Re: [2-DefaultMapping] Proposal

From: Martin Vojtek <voytoo_at_gmail.com>
Date: Thu, 5 Mar 2015 21:31:13 +0100

Hi Olena and Kiev UA JUG,

thank you very much for your feedback.

ad 1)

there are several specifications related to JSON and they are not
consistent in the definition of JSON.

According to RF4627 (http://www.ietf.org/rfc/rfc4627.txt):

A JSON text is a serialized object or array.

There are also several online JSON validators, which supports the idea,
e.g. http://jsonlint.com/
There are also several JSON validators, which are supporting all JSON
values, not only object or array.

On the other hand, there is also newer proposed standard RFC 7159, which
relaxes this https://datatracker.ietf.org/doc/rfc7159

   A JSON text is a sequence of tokens. The set of tokens includes six
   structural characters, strings, numbers, and three literal names.

   A JSON text is a serialized value. Note that certain previous
   specifications of JSON constrained a JSON text to be an object or an

   array. Implementations that generate only objects or arrays where a
   JSON text is called for will be interoperable in the sense that all
   implementations will accept these as conforming JSON texts.

I have to confess, that my first non-public proposal was accepting also
JSON values.

I see the following advantages supporting only objects and arrays as JSON
text:

1. JSR 353: JavaTM API for JSON Processing (
https://jcp.org/en/jsr/detail?id=353)
JsonReader and JsonParser support only objects and arrays.

JsonReader jsonReader = Json.createReader(new StringReader("1"));
System.out.println(jsonReader.read()); //javax.json.JsonException: Empty
stream

There is no event emitted:
JsonParser parser = Json.createParser(new StringReader("1"));
while (parser.hasNext()) {
     JsonParser.Event event = parser.next();
     System.out.println("event="+event); //never happens
}

JSON Binding should be compatible with JSR 353, and it is expected, that
JSON Binding RI will use JSON Processing RI.

2. Interoperability as stated in RFC 7159

3. I don't see much value added supporting this use case

*I definitely want to hear some other opinions on this topic. *

ad 2)

It is clear that escaping must be supported. I will add some explicit
examples to express this.

ad 3)

The intention of these examples was to express, that default implementation
of Map should be LinkedHashMap<String, Object>.
Key/value pairs in JSON objects are not ordered, but it is very practical
to have these pairs ordered.

From my point of view, the most reasonable implementation for JSON array is
ArrayList<Object>.

If I specify default implementation for JSON object, it makes sense to
specify also default implementation for JSON array (at least for
consistency).

Other advantage is predictability from the user of this API. If we don't
specify this, this will be probably implemented differently by different
implementations.
I can imagine that different fields could have different implementations
like Arrays.asList(...), Collections.EMPTY_LIST and so on.
This can be problematic in some use cases.
Specifying default implementations (for default mapping) will improve
operability and provide some sensible defaults for the user of the API.

*I definitely want to hear some other opinions on this topic too. *

MartinV


On Thu, Mar 5, 2015 at 5:58 PM, Olena Syrota <sirotae_at_gmail.com> wrote:

> Hi guys,
>
> More feedback from Kiev UA JUG (with Oleg Tsal-Tsalko and Andrii Rodionov).
>
> 1. JSON value formatting. Let me propose to follow The JSON Data
> Interchange Format (
> http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
> Due to this document JSON value is printed without square brackets "[...]".
> Square brakets are used for JSON array.
>
> e.g.
>
> - jsonb.fromJson("1", Byte.class)
>
> instead of
>
> - jsonb.fromJson("[1]", Byte.class), etc.
>
>
> 2. More cases for String mapping should be considered. Due to
> http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf,
> page 5, we should add mapping cases for \", /, \\, \r, \n, \t, \f, \b,
> \uXXXX.
> See
> https://github.com/sirotae/jsonb-spec-ua-adopt/tree/master/examples/src/test/java/jug/ua/jsonb/examples/default_mapping,
> file StringMapping.java
>
> 3. Structure Mapping from Json.
> Case 1. Instead of
>
> - Collection<Object> collection =
> (ArrayList<Object>)jsonb.fromJson("[{\"value\":\"first\"},
> {\"value\":\"second\"}]", Object.class);
>
>
> Let me propose:
>
> - List<Object> act = (List)jsonb.fromJson("[{\"value\":\"first\"},
> {\"value\":\"second\"}]", Object.class);
>
>
> Case 2. Instead of
>
> - Map<String, Object> map =
> (LinkedHashMap<String,Object>)jsonb.fromJson("{\"name\":\"unknown
> object\"}", Object.class);
>
>
> let me propose
>
> - Map<String, Object> map = (Map)jsonb.fromJson("{\"name\":\"unknown
> object\"}", Object.class);
>
>
>
> Thank you
> Olena
>
> 2015-03-04 0:05 GMT+02:00 Eugen Cepoi <cepoi.eugen_at_gmail.com>:
>
>> The way byte arrays are being ser/de can be a config. option.
>> The advantage of base64 is that it produces much smaller json than using
>> an array.
>> I didn't benchmark ser/de speed when using one or the other but I guess
>> the difference is probably not so big.
>>
>> Eugen
>>
>> 2015-03-03 13:47 GMT-08:00 Hendrik Dev <hendrikdev22_at_gmail.com>:
>>
>> Hi all,
>>>
>>> what about byte[] serialization and deserialization to/from base64?
>>> For me its natural (like proposed by MartinV) so ser/deser into a
>>> array of bytes like [3,-1,33,-11] but some json binding frameworks out
>>> there ser/deser byte[] to/from a base64 encoded string by default.
>>> To make the spec compatible with them maybe we should consider to
>>> support both?
>>>
>>> Wdyt?
>>>
>>> Thanks
>>> Hendrik
>>>
>>>
>>> On Fri, Feb 27, 2015 at 5:45 PM, Martin Grebac <martin.grebac_at_oracle.com>
>>> wrote:
>>> >
>>> > Please ignore the last point - bad example. Will provide multiple
>>> examples
>>> > within the generics topic.
>>> > MartiNG
>>> >
>>> >
>>> > On 27.02.15 10:03, Martin Grebac wrote:
>>> >>
>>> >> On 25.02.15 20:29, Przemyslaw Bielicki wrote:
>>> >>>
>>> >>>
>>> >>> Yes exactly like this.
>>> >>>
>>> >> Not sure exactly like what - are you suggesting both scenarios? Root
>>> level
>>> >> as well as nested?
>>> >>
>>> >>> Without typetoken it could be difficult as Optional is a final class
>>> thus
>>> >>> we cannot make custom classes like OptionalFoo extends Optional<Foo>
>>> >>>
>>> >>> 25 lut 2015 19:35 "Eugen Cepoi" <cepoi.eugen_at_gmail.com
>>> >>> <mailto:cepoi.eugen_at_gmail.com>> napisaƂ(a):
>>> >>>
>>> >>> If it is about Optional at the mapping level I am not sure there
>>> >>> is a need to make it appear in the spec.
>>> >>>
>>> >> In spec we have to define (or decide to not to define) the behaviour
>>> for
>>> >> Optional within default mapping at least to not cause portability
>>> problems.
>>> >>
>>> >>> The use case I would see with optional at root level is when the
>>> >>> root value it self is null... with typetoken could look like (I
>>> >>> don't know how you plan to handle generics):
>>> >>>
>>> >>> Optional<Foo> optFoo = jsonb.fromJson(json, new
>>> >>> TypeToken<Optional<Foo>>() {})
>>> >>>
>>> >> What is the value that this support brings to JSON Binding? Does this
>>> have
>>> >> value for further work with optFoo?
>>> >> The call requires constructing the specific type, requires us to
>>> remove
>>> >> type checking from the method signature which is useful in non-generic
>>> >> cases, and I'm not sure about the value or problem it actually solves.
>>> >>
>>> >>> But the most common would be to have optional nested in Pojo like
>>> >>> structures. In that case it would be handled directly by impls.
>>> >>>
>>> >> We're again inherently discussing generics here with Optional, too.
>>> And
>>> >> the same as above applies - we need portable behaviour. So, let's say
>>> we
>>> >> have
>>> >>
>>> >> public class B {
>>> >> Optional<C> c;
>>> >> }
>>> >> public class C {
>>> >> Optional<List<Optional<String>>> s;
>>> >> OptionalInt i;
>>> >> D<String,Long> d;
>>> >> }
>>> >> public class D<T1,T2> {
>>> >> List<T1> l1;
>>> >> Optional<T2> t2;
>>> >> }
>>> >>
>>> >> And you want to be marshalling / unmarshalling from / into this
>>> structure.
>>> >> How would the implementation at runtime be able to defer and create
>>> proper
>>> >> types for the individual properties?
>>> >>
>>> >> MartiNG
>>> >>
>>> >>> 2015-02-25 5:27 GMT-08:00 Martin Grebac <
>>> martin.grebac_at_oracle.com
>>> >>> <mailto:martin.grebac_at_oracle.com>>:
>>> >>>
>>> >>> On 25.02.15 8:44, Przemyslaw Bielicki wrote:
>>> >>>
>>> >>> The trouble with Optional is that it is typed, and as
>>> >>> such its use is too complex within the api methods we
>>> >>> have now compared to the minimal benefit it brings.
>>> >>>
>>> >>> Anyway I think it should be impl specific feature - sorry
>>> >>> for the noise.
>>> >>>
>>> >>> After re-reading I think I may have been too fast and
>>> >>> misunderstood the usecase. Before I jump into my rant on
>>> >>> Optional :) , would you please give some examples of the
>>> >>> expected outcomes, say based on MartinV's default mapping
>>> >>> examples?
>>> >>>
>>> >>> I think it makes sense to get some clarity into this and make
>>> >>> decisions whether the support for Optional should be in the
>>> >>> spec, whether it should be default, and whether it should be
>>> >>> spec defined configuration, mostly because Optional has value
>>> >>> wrt lambdas. Thus I also expect the reasoning will likely
>>> have
>>> >>> to include the expected stream use? I don't find Optional
>>> >>> bringing any significant value outside of streams.
>>> >>>
>>> >>> MartiNG
>>> >>>
>>> >
>>> > --
>>> > Martin Grebac, SW Engineering Manager
>>> > Oracle Czech, Prague
>>> >
>>>
>>>
>>>
>>> --
>>> Hendrik Saly (salyh, hendrikdev22)
>>> @hendrikdev22
>>> PGP: 0x22D7F6EC
>>>
>>
>>
>