如果javax.json文档建议创建JsonObject的方法是使用提供的构建器,如:
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();
此示例添加了给定键的值。 在现实生活中,这些值可能来自某些(pojo)域对象,如:
JsonBuilderFactory factory = Json.createBuilderFactory(config);
JsonObject value = factory.createObjectBuilder()
.add("firstname", customer.getFirstame())
.add("lastname", customer.getLastame())
.add("age", customer.getAge())
....
如果key或value为null,JsonOBjectBuilder会抛出一个NPE。如果客户没有注册年龄,则上述代码将抛出NPE。
所以基本上对于我添加的每个字段,我必须检查值是否为null并添加实际值,否则不添加字段或为密钥添加JsonValue.NULL。 这导致了很多(不希望的)样板......
在我的情况下,我最终得到了自定义JsonUtils类,包括各种静态方法,如:
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);
}
}
然后致电:
builder = Json.createObjectBuilder();
JsonUtils.add(builder, "id", customer.getId());
JsonUtils.add(builder, "name", customer.getName());
JsonUtils.add(builder, "gender", customer.getGender());
builder.build()
但是如果感觉不对劲的话。 为什么javax.json没有提供更简单的方法来添加空值(没有if else样板)或者我错过了什么?
我对JSR-353 api的主要批评是,尽管它看起来像一个非常好的 流利的 api(参见apidoc的顶级示例),但实际上它不是。
答案 0 :(得分:12)
可能很难从工厂获得JsonObjectBuilder
实施,但您可以更简单。
创建一个JsonObjectBuilder
装饰器类,用于检查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.
..
}
以及如何使用它:
JsonObjectBuilder builder = NullAwareJsonObjectBuilder.wrap(
factory.createObjectBuilder());
builder.add("firstname", customer.getFirstame())
.add(...
答案 1 :(得分:1)
另一种可能的解决方案是使用简单和精益助手将值包装到JsonValue
对象中,如果值为null,则返回JsonValue.NULL
。
以下是一个例子:
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);
}
}
用法很简单:
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();
像Json.createObjectBuilder().add(KEY, ref).build().get(KEY);
之类的构造看起来有点奇怪,但它是迄今为止我发现的JsonValue
值的唯一可移植方式。
事实上,在JavaEE8中,您可以将其替换为:
Json.createValue()
或基础:
JsonProvider.provider().createValue()
呼叫。