Java JSON 支持在没有架构的情况下获取和设置深度值的库?
Java JSON library supporting getting and setting deep values without schema?
我正在调用某个服务的 API,它们 return 是一个巨大的 JSON,实际上有大约一百个字段和十几个嵌套对象。但是,我不需要所有这些。事实上,在执行 GET 或 POST 时,我确实需要 3 到 7 个字段。我非常想避免在我的应用程序中仅针对 serialize/deserialize 几个字段使用这种复杂的模型。
本质上,我想实现:
- 将他们巨大的 nested JSON 字符串反序列化为我的 flat POJO。
- 使用平面 POJO 投影处理我的代码。
- 将我的平面 POJO 序列化到他们复杂的嵌套模式。
到目前为止我的解决方案是依赖 JsonPath:
- 为我的平面 POJO 中的字段创建自定义注释,例如:
@JsonPathField("$.very.deeply.nested.field.value")
private String theOnlyFieldIneed;
创建一个 util 方法,该方法使用反射生成 <fieldName, JsonPath.readValue()>
的映射,我将其提供给 Jackson objectMapper 以生成我的 POJO。所以反序列化到平面 POJO 部分是可行的。
然而,对于序列化,情况更糟,因为如果字符串中不存在路径,JsonPath 会抛出异常。喜欢,
// This will throw an exception:
DocumentContext document = JsonPath.using(jsonPathConfig).parse("{}");
document.set("$.not.even.deepest", value);
- 为了解决这个问题,我添加了一种原始模式作为字符串以提供给 JsonParh.parse(Pojo.Prototype),但这很丑陋、乏味且容易出错。
基本上,我正在寻找 Immutable.JS 种行为:Collection.SetIn
您可以使用 Kson (https://github.com/kantega/kson),它非常直接地支持从嵌套结构中提取值。
public class DecodeExample {
public static class Address {
final String street;
final String zip;
public Address(String street, String zip) {
this.street = street;
this.zip = zip;
}
}
static class User {
final String name;
final Address address;
User(String name, Address address) {
this.name = name;
this.address = address;
}
}
public static void main(String[] args) {
final JsonDecoder<Address> adressDecoder =
obj(
field("street", stringDecoder),
field("zip", stringDecoder.ensure(z -> z.length() < 5)), //You can add constraints right here in the converter
Address::new
);
JsonResult<JsonValue> json =
JsonParser.parse(jsonString);
Address address =
json.field("model").field("leader").field("address").decode(adressDecoder).orThrow(RuntimeException::new);
System.out.println(address);
JsonResult<Address> userAddress =
json.field("model").field("users").index(0).field("address").decode(adressDecoder);
System.out.println(userAddress);
}
}
我正在调用某个服务的 API,它们 return 是一个巨大的 JSON,实际上有大约一百个字段和十几个嵌套对象。但是,我不需要所有这些。事实上,在执行 GET 或 POST 时,我确实需要 3 到 7 个字段。我非常想避免在我的应用程序中仅针对 serialize/deserialize 几个字段使用这种复杂的模型。
本质上,我想实现:
- 将他们巨大的 nested JSON 字符串反序列化为我的 flat POJO。
- 使用平面 POJO 投影处理我的代码。
- 将我的平面 POJO 序列化到他们复杂的嵌套模式。
到目前为止我的解决方案是依赖 JsonPath:
- 为我的平面 POJO 中的字段创建自定义注释,例如:
@JsonPathField("$.very.deeply.nested.field.value")
private String theOnlyFieldIneed;
创建一个 util 方法,该方法使用反射生成
<fieldName, JsonPath.readValue()>
的映射,我将其提供给 Jackson objectMapper 以生成我的 POJO。所以反序列化到平面 POJO 部分是可行的。然而,对于序列化,情况更糟,因为如果字符串中不存在路径,JsonPath 会抛出异常。喜欢,
// This will throw an exception:
DocumentContext document = JsonPath.using(jsonPathConfig).parse("{}");
document.set("$.not.even.deepest", value);
- 为了解决这个问题,我添加了一种原始模式作为字符串以提供给 JsonParh.parse(Pojo.Prototype),但这很丑陋、乏味且容易出错。
基本上,我正在寻找 Immutable.JS 种行为:Collection.SetIn
您可以使用 Kson (https://github.com/kantega/kson),它非常直接地支持从嵌套结构中提取值。
public class DecodeExample {
public static class Address {
final String street;
final String zip;
public Address(String street, String zip) {
this.street = street;
this.zip = zip;
}
}
static class User {
final String name;
final Address address;
User(String name, Address address) {
this.name = name;
this.address = address;
}
}
public static void main(String[] args) {
final JsonDecoder<Address> adressDecoder =
obj(
field("street", stringDecoder),
field("zip", stringDecoder.ensure(z -> z.length() < 5)), //You can add constraints right here in the converter
Address::new
);
JsonResult<JsonValue> json =
JsonParser.parse(jsonString);
Address address =
json.field("model").field("leader").field("address").decode(adressDecoder).orThrow(RuntimeException::new);
System.out.println(address);
JsonResult<Address> userAddress =
json.field("model").field("users").index(0).field("address").decode(adressDecoder);
System.out.println(userAddress);
}
}