[英]Json Jackson won't unwrap root element
I've been trying to deserialize an array of JSON objects for a while now, and all the answers on the inte.net are either deprecated or just don't work for me.一段时间以来,我一直在尝试反序列化 JSON 对象的数组,而 inte.net 上的所有答案要么已弃用,要么对我不起作用。
The code below always returns a MismatchedInputException
with the following message:下面的代码总是返回带有以下消息的
MismatchedInputException
:
...MismatchedInputException: Root name ('builders')
does not match expected ('Builder[]') for type `[LModel.Attributes.Builder;`
Below is my code for my DTO:以下是我的 DTO 代码:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonRootName;
@JsonRootName("builders")
public class Builder {
private String id;
private String builder;
@JsonProperty("id")
public void setId(String id) {
this.id = id;
}
@JsonProperty("name")
public void setBuilder(String builder) {
this.builder = builder;
}
public String getBuilder() {
return builder;
}
public String getId(){
return id;
}
}
And here we have our deserializer:在这里我们有我们的反序列化器:
var json = response.body();
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
var builders = mapper.readValue(json, Builder[].class);
And this is my JSON:这是我的 JSON:
{
"builders": [
{
"id": 1,
"name": "Haley LLC"
},
{
"id": 2,
"name": "Stoltenberg, Mayert and Weimann"
},
{
"id": 3,
"name": "Ziemann Group"
},
{
"id": 4,
"name": "Monahan - Torp"
},
{
"id": 5,
"name": "Fritsch, Harber and Lemke"
}
]
}
Annotation @JsonRootName
would work as expect if there would be a single object, not a JSON-array.如果只有一个 object 而不是 JSON 数组,注释
@JsonRootName
将按预期工作。 In this case, we need a different approach.在这种情况下,我们需要一种不同的方法。
You can prepare an ObjectReader
by specifying TypeReference
of type List<Builder>
using method ObjectMapper.readerFor( TypeReference )
.您可以使用方法
ObjectMapper.readerFor( TypeReference )
指定List<Builder>
类型的TypeReference
来准备ObjectReader
。
And in order to unwrap this JSON-array, we can make use of the method ObjectReader.withRootName()
.为了打开这个 JSON 数组,我们可以使用
ObjectReader.withRootName()
方法。
Here's how it might look like:它可能是这样的:
String json = """
{
"builders": [
{
"id": 1,
"name": "Haley LLC"
},
... // other elements
]
}
""";
ObjectMapper mapper = new ObjectMapper();
ObjectReader objectReader = mapper
.readerFor(new TypeReference<List<Builder>>() {})
.withRootName("builders");
List<Builder> builders = objectReader.readValue(json);
builders.forEach(System.out::println);
Output: Output:
Builder{id='1', builder='Haley LLC'}
Builder{id='2', builder='Stoltenberg, Mayert and Weimann'}
Builder{id='3', builder='Ziemann Group'}
Builder{id='4', builder='Monahan - Torp'}
Builder{id='5', builder='Fritsch, Harber and Lemke'}
@JsonRootName
on top of the Builder
class is not needed in this case.在这种情况下,不需要
Builder
@JsonRootName
之上的 @JsonRootName。 You can remove it, if you have no another cases with a single Builder
object being wrapped in the JSON.你可以删除它,如果你没有其他案例,单个
Builder
object 被包装在 JSON 中。
Also, applying deserialization feature UNWRAP_ROOT_VALUE
is not required for this solution to work.此外,此解决方案不需要应用反序列化功能
UNWRAP_ROOT_VALUE
。
Could you try with a wrapper class:你能试试包装器 class:
public class Builder{
public int id;
public String name;
}
public class Root{
public ArrayList<Builder> builders;
}
ObjectMapper mapper = new ObjectMapper();
Root root = mapper.readValue(strJson, Root.class);
You could just Deserialize to Map<String, List<Builder>>
and then get
by key "builders".您可以反序列化为
Map<String, List<Builder>>
,然后通过键“builders” get
。
Even semantically it's not a bad representation because it is, after all, a JS Dictionary object with a list of Builders in it under the key "builders".即使在语义上它也不是一个糟糕的表示,因为毕竟它是一个 JS 字典 object,其中在键“builders”下有一个 Builders 列表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.