繁体   English   中英

Json Jackson 不会展开根元素

[英]Json Jackson won't unwrap root element

一段时间以来,我一直在尝试反序列化 JSON 对象的数组,而 inte.net 上的所有答案要么已弃用,要么对我不起作用。

下面的代码总是返回带有以下消息的MismatchedInputException

...MismatchedInputException: Root name ('builders')
does not match expected ('Builder[]') for type `[LModel.Attributes.Builder;`

以下是我的 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;
    }
}

在这里我们有我们的反序列化器:

var json = response.body();


mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
var builders = mapper.readValue(json, Builder[].class);

这是我的 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"
        }
    ]
}

如果只有一个 object 而不是 JSON 数组,注释@JsonRootName将按预期工作。 在这种情况下,我们需要一种不同的方法。

您可以使用方法ObjectMapper.readerFor( TypeReference )指定List<Builder>类型的TypeReference来准备ObjectReader

为了打开这个 JSON 数组,我们可以使用ObjectReader.withRootName()方法。

它可能是这样的:

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:

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'}

笔记

在这种情况下,不需要Builder @JsonRootName之上的 @JsonRootName。 你可以删除它,如果你没有其他案例,单个Builder object 被包装在 JSON 中。

此外,此解决方案不需要应用反序列化功能UNWRAP_ROOT_VALUE

你能试试包装器 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);

您可以反序列化为Map<String, List<Builder>> ,然后通过键“builders” get

即使在语义上它也不是一个糟糕的表示,因为毕竟它是一个 JS 字典 object,其中在键“builders”下有一个 Builders 列表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM