[英]Jackson: deserialize missing field to Kotlin/Java List
I have the answer to my own question, so I post both the answer and solution, as explicitly encouraged by Jeff Atwood.我有自己问题的答案,因此我发布了答案和解决方案,这是 Jeff Atwood 明确鼓励的。 My question was originally for Kotlin, but while trying to find a solution, I also tried Java, so I provide the question and solution in both Java and Kotlin.) My question was originally for Kotlin, but while trying to find a solution, I also tried Java, so I provide the question and solution in both Java and Kotlin.)
Given this deserializable Product
class:鉴于此可反序列化Product
class:
data class Product(val name: String, val prices: List<Int>)
and this json string that lacks the prices
field:而这个缺少prices
字段的 json 字符串:
{"name": "Computer"}
how can I deserialize the json string to a Product
object using Jackson?如何使用 Jackson 将 json 字符串反序列化为Product
object?
I tried this:我试过这个:
data class Product(val name: String, val prices: List<Int>)
// Missing "prices" field
val json = """{"name": "Computer"}"""
// "prices" field included works fine
// val json = """{"name": "Computer", "prices": [1,2,3]}"""
val mapper = ObjectMapper().registerKotlinModule()
val product = mapper.readValue<Product>(json)
println(product)
but it results in this exception:但这会导致此异常:
com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of
[simple type, class MainKt$main$Product] value failed for JSON property prices due to
missing (therefore NULL) value for creator parameter prices which is a non-nullable type
at [Source: (String)"{"name": "Computer"}"; line: 1, column: 20]
(through reference chain: MainKt$main$Product["prices"])
For Java the Product
class would be:对于 Java, Product
class 将是:
class Product {
private String name;
private List<Integer> prices;
public Product(String name, List<Integer> prices) {
this.name = name;
this.prices = prices;
}
@Override
public String toString() {
return "Product{name='" + name + "\", prices=" + prices + '}';
}
}
with this Jackson code:使用此 Jackson 代码:
String json = "{\"name\": \"Computer\"}";
// String json = "{\"name\": \"Computer\", \"prices\": [1,2,3]}";
ObjectMapper mapper = new ObjectMapper();
// ParameterNamesModule is needed for non-arg constructor when not using Jackson annotations
mapper.registerModule(new ParameterNamesModule());
Product product = mapper.readValue(json, Product.class);
// Shows "prices=null", while "prices=[]" is required
System.out.println(product);
But this sets prices
to null
instead of an empty list.但这将prices
设置为null
而不是空列表。
This solution is for Jackson 2.11 and higher.此解决方案适用于 Jackson 2.11 及更高版本。 It uses the jackson-module-kotlin
Maven artifact.它使用jackson-module-kotlin
Maven 工件。
val kotlinModule = KotlinModule.Builder()
.configure(KotlinFeature.NullToEmptyCollection, true)
.build()
val mapper = ObjectMapper().registerModule(kotlinModule)
val product = mapper.readValue(json, Product::class.java)
println(product)
So the solution uses KotlinFeature.NullToEmptyCollection
, which has the following documentation:所以该解决方案使用KotlinFeature.NullToEmptyCollection
,它具有以下文档:
Default: false.默认值:假。 Whether to deserialize null values for collection properties as empty collections.是否将集合属性的 null 值反序列化为空 collections。
There is also a map version: KotlinFeature.NullToEmptyMap
.还有一个 map 版本: KotlinFeature.NullToEmptyMap
。
For version 2.9 and 2.10 you can use the nullToEmptyCollection
default parameter of the KotlinModule
constructor.对于 2.9 和 2.10 版本,您可以使用KotlinModule
构造函数的nullToEmptyCollection
默认参数。
Annotated Product
class:注释Product
class:
class Product {
private String name;
private List<Integer> prices;
public Product(@JsonProperty("name") String name,
@JsonProperty("prices")
@JsonSetter(nulls = Nulls.AS_EMPTY) List<Integer> prices
) {
this.name = name;
this.prices = prices;
}
@Override
public String toString() {
return "Product{name='" + name + "\', prices=" + prices + '}';
}
}
Jackson code: Jackson 代码:
String json = "{\"name\": \"Computer\"}";
ObjectMapper mapper = new ObjectMapper();
Product product = mapper.readValue(json, Product.class);
System.out.println(product); // Product{name='Computer', prices=[]}
The key part in this solution is @JsonSetter(nulls = Nulls.AS_EMPTY)
, which sets the missing or null json field to an empty list in Java.该解决方案的关键部分是@JsonSetter(nulls = Nulls.AS_EMPTY)
,它将缺失的或 null json 字段设置为 ZD52387880E1EA22817A72D3759Z23 中的空列表。
The number of verbose annotations, such as @JsonProperty("prices")
can be reduced by using the jackson-module-parameter-names
Maven artifact.可以通过使用jackson-module-parameter-names
Maven 工件来减少详细注释的数量,例如@JsonProperty("prices")
。 Then only @JsonSetter(nulls = Nulls.AS_EMPTY)
is needed.然后只需要@JsonSetter(nulls = Nulls.AS_EMPTY)
。
This solution requires the jackson-module-parameter-names
Maven artifact.此解决方案需要jackson-module-parameter-names
Maven 工件。 When using this module/artifact, don't forget to add the -parameters
compiler argument.使用此模块/工件时,不要忘记添加-parameters
编译器参数。
Product
class Jackson without annotations: Product
class Jackson 无注释:
class Product {
private String name;
private List<Integer> prices;
public Product(String name, List<Integer> prices) {
this.name = name;
this.prices = prices;
}
@Override
public String toString() {
return "Product{name='" + name + "\", prices=" + prices + '}';
}
}
Jackson code: Jackson 代码:
String json = "{\"name\": \"Computer\"}";
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new ParameterNamesModule());
mapper.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
Product product = mapper.readValue(json, Product.class);
System.out.println(product);
The ParameterNamesModule
model is required to allow Jackson to reflect the Product
constructor parameters by name, so that @JsonProperty("prices")
isn't required anymore.需要ParameterNamesModule
model 以允许 Jackson 按名称反映Product
构造函数参数,因此不再需要@JsonProperty("prices")
。 And JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)
is used to convert missing or null json fields to a list.而JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)
用于将缺失或 null json 字段转换为列表。
Your Product class need to implement Serializable class.您的产品 class 需要实现可序列化 class。 It can make consistency data.它可以制作一致性数据。
class Product implements Serializable {
..............
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.