<< Back to previous view

[JSON_PROCESSING_SPEC-36] JSON builder improvements Created: 07/Dec/12  Updated: 10/Dec/12  Resolved: 10/Dec/12

Status: Closed
Project: json-processing-spec
Component/s: None
Affects Version/s: 1.0-pr
Fix Version/s: 1.0-pr

Type: Improvement Priority: Major
Reporter: jitu Assignee: jitu
Resolution: Fixed Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: jitu

 Description   

Feedback from Mark Reinhold
--------------------------------------
The EDR javadoc for JsonObject contains this builder-pattern example:

JsonObject object = new JsonBuilder()
        .beginObject()
            .add("firstName", "John")
            .add("lastName", "Smith")
            .add("age", 25)
            .beginObject("address")
                .add("streetAddress", "21 2nd Street")
                .add("city", "New York")
                .add("state", "NY")
                .add("postalCode", "10021")
            .endObject()
            .beginArray("phoneNumber")
                .beginObject()
                    .add("type", "home")
                    .add("number", "212 555-1234")
                .endObject()
                .beginObject()
                    .add("type", "home")
                    .add("number", "646 555-4567")
                .endObject()
            .endArray()
        .endObject()
    .build();

One problem with this style is that the structure of the object being
constructed is not reflected in the syntax of the expression. A reader
must visually scan for "begin" and "end" methods in order to understand
the resulting object structure, or even just to indent the code.

Here's a variant of the above example written against a (hypothetical)
alternative API:

JsonObject value = new JsonObjectBuilder()
        .add("firstName", "John")
        .add("lastName", "Smith")
        .add("age", 25)
        .add("address", new JsonObjectBuilder()
             .add("streetAddress", "21 2nd Street")
             .add("city", "New York")
             .add("state", "NY")
             .add("postalCode", "10021"))
        .add("phoneNumber", new JsonArrayBuilder()
             .add(new JsonObjectBuilder()
                  .add("type", "home")
                  .add("number", "212 555-1234"))
             .add(new JsonObjectBuilder()
                  .add("type", "home")
                  .add("number", "646 555-4567")))
        .build();

Note how the structure of the resulting object is obvious from the
structure of the expression, which (by the way) is indented correctly
(at least by Emacs) without any manual effort at all. You also don't
need the "end" methods.

Have you considered a design that would support this style? I think
it's much more readable.
--------------------------



 Comments   
Comment by jitu [ 07/Dec/12 11:01 PM ]

The current design was used by JsonBuilder as well as JsonGenerator, and it is more suitable from streaming generation. Now JsonGenerator is moved to its own abstraction, this proposal is appealing.

Here are some observations:

  • proposal seems to be simpler
  • here one has to start with JsonObjectBuilder and JsonArrayBuilder. In the current design, one just starts with JsonBuilder always.
  • uses two classes, instead of all the other baggage like JsonBuildable, JsonBuilder
  • avoids the generics trick which end() method is doing.
  • end() is not required
  • The earlier design also works for generating JSON in a streaming fashion. Now(after EDR) JsonGenerator uses its own abstraction, so this seems more suitable now.
  • I think this is also guarantees compile-time safety to the building objects similar to the current one i.e one cannot add JSON array values in objects (name/value pairs)
  • I think we can still add existing JsonArray/JsonObject

I would like to incorporate the Marc's proposal.

Comment by jitu [ 10/Dec/12 08:29 PM ]

Incorporating the suggested proposal.

Generated at Sun Apr 20 07:45:30 UTC 2014 using JIRA 4.0.2#472.