JSR-353 How to add null values using javax.json.JsonObjectBuilder

早过忘川 提交于 2019-11-30 01:34:12

问题


AS the javax.json docs suggest the way to create a JsonObject is using the provided builders like:

JsonBuilderFactory factory = Json.createBuilderFactory(config);
 JsonObject value = factory.createObjectBuilder()
     .add("firstName", "John")
     .add("lastName", "Smith")
     .add("age", 25)
     .add("address", factory.createObjectBuilder()
         .add("streetAddress", "21 2nd Street")
         .add("city", "New York")
         .add("state", "NY")
         .add("postalCode", "10021"))
     .add("phoneNumber", factory.createArrayBuilder()
         .add(factory.createObjectBuilder()
             .add("type", "home")
             .add("number", "212 555-1234"))
         .add(factory.createObjectBuilder()
             .add("type", "fax")
             .add("number", "646 555-4567")))
     .build();

This example adds values for the gives keys. In real life the values are probably derived from some (pojo) domain object like:

JsonBuilderFactory factory = Json.createBuilderFactory(config);
 JsonObject value = factory.createObjectBuilder()
     .add("firstname", customer.getFirstame())
     .add("lastname", customer.getLastame())
     .add("age", customer.getAge())
     ....

The JsonOBjectBuilder throw a NPE in case key or value is null. In case the customer has no registered age then above code will throw a NPE.

So basically for every field I add I have to check if the value is null or not and add the actual value and otherwise do not add the field or add JsonValue.NULL for the key. This causes a lot of (undesired) boilerplate...

In my case I ended up with custom JsonUtils class including various static methods like:

public static void add(JsonObjectBuilder builder, String name, Long value) {
    if (value == null) {
        builder.add(name,  JsonValue.NULL);
    }
    else {
        builder.add(name, value);
    }
}

public static void add(JsonObjectBuilder builder, String name, String value) {
    if (value == null) {
        builder.add(name,  JsonValue.NULL);
    }
    else {
        builder.add(name, value);
    }
}

and then calling:

builder = Json.createObjectBuilder();
JsonUtils.add(builder, "id", customer.getId());
JsonUtils.add(builder, "name", customer.getName());
JsonUtils.add(builder, "gender", customer.getGender());
builder.build()

But someway if feels not right. Why does the javax.json provide no easier way to add null values (without if else boilerplate) or am I missing something?

My main point of critism against the JSR-353 api is that despite it looks like a really nice fluent api (see top example from apidoc) but in reality it is not.


回答1:


It might be difficult to get your JsonObjectBuilder implementation from the factory but you can make it simpler.

Create a JsonObjectBuilder decorator class that checks for null:

public class NullAwareJsonObjectBuilder implements JsonObjectBuilder {
    // Use the Factory Pattern to create an instance.
    public static JsonObjectBuilder wrap(JsonObjectBuilder builder) {
      if (builder == null) {
        throw new IllegalArgumentException("Can't wrap nothing.");
      }
      return new NullAwareJsonObjectBuilder(builder);
    }

    // Decorated object per Decorator Pattern.
    private final JsonObjectBuilder builder;

    private NullAwareJsonObjectBuilder(JsonObjectBuilder builder) {
      this.builder = builder;
    }

    public JsonObjectBuilder add(String name, JsonValue value) {
      builder.add(name, (value == null) ? JsonValue.NULL : value);
    }

    // Implement all other JsonObjectBuilder methods.
    ..
}

And how you to use it:

JsonObjectBuilder builder = NullAwareJsonObjectBuilder.wrap(
        factory.createObjectBuilder());
builder.add("firstname", customer.getFirstame())
    .add(...



回答2:


Another possible solution is to use simple and lean helper to wrap a value into JsonValue object or return JsonValue.NULL if value is null.

Here is an example:

public final class SafeJson {
    private static final String KEY = "1";

    //private ctor with exception throwing

    public static JsonValue nvl(final String ref) {
        if (ref == null) {
            return JsonValue.NULL;
        }
        return Json.createObjectBuilder().add(KEY, ref).build().get(KEY);
    }

    public static JsonValue nvl(final Integer ref) {
        if (ref == null) {
            return JsonValue.NULL;
        }
        return Json.createObjectBuilder().add(KEY, ref).build().get(KEY);
    }

    public static JsonValue nvl(final java.sql.Date ref) {
        if (ref == null) {
            return JsonValue.NULL;
        }
        return Json.createObjectBuilder().add(KEY, ref.getTime()).build().get(KEY);
    }
}

Usage is simple:

Json.createObjectBuilder().add("id", this.someId)
    .add("zipCode", SafeJson.nvl(this.someNullableInt))
    .add("phone", SafeJson.nvl(this.someNullableString))
    .add("date", SafeJson.nvl(this.someNullableDate))
    .build(); 

Constructs like Json.createObjectBuilder().add(KEY, ref).build().get(KEY); looks a little bit weird but it is the only portable way to wrap value into JsonValue I've found so far.

In fact in JavaEE8 you can replace it with:

Json.createValue()

or underlying:

JsonProvider.provider().createValue()

call.



来源:https://stackoverflow.com/questions/22363925/jsr-353-how-to-add-null-values-using-javax-json-jsonobjectbuilder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!