【问题标题】:Deserializing JSON using spring boot into a POJO with a list of generic objects使用 Spring Boot 将 JSON 反序列化为带有通用对象列表的 POJO
【发布时间】:2018-06-02 03:40:23
【问题描述】:

我正在尝试反序列化搜索 API 的 JSON 结果。搜索 API(我在这里简化了)有一个主对象,其中包含有关搜索的元数据,然后有一个搜索对象的列表。我正在尝试使用通用对象列表来实现这一点

我已经在没有 的情况下测试了这些类,并且一切都完全按照我的意愿工作。

TestSearch.java

public class TestSearch<T> {

    private String count;
    private List<T> results;

    public String getCount() {
        return count;
    }

    public void setCount(String count) {
        this.count = count;
    }

    public List<T> getResults() {
        return results;
    }

    public void setResults(List<T> results) {
        this.results = results;
    }
}

TestResult.java

public class TestResult {

    private String name;
    private String description;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

TestController.java

@RequestMapping("/test/json")
public String testGetJson() {
    return "{\"count\":3,\"results\":[{\"name\":\"result 1\",\"description\":\"this is the first result\",\"extra\":\"property\"},{\"name\":\"result 2\",\"description\":\"tqbf\"},{\"name\":\"result 3\",\"description\":\"jotlz\"}]}";
}

@RequestMapping("/test/testserialize")
public List<TestResult> testSerialize() {
    TestSearch<TestResult> testSearch = new RestTemplate().getForObject("http://localhost:8957/test/json", new TestSearch<TestResult>().getClass());

    List<TestResult> results = testSearch.getResults();

    results.forEach(result -> {
        result.setName("new value");
    });

    return results;
}

JSON(只是为了让内容更具可读性)

{
    "count": 3,
    "results": [
        {
            "name": "result 1",
            "description": "this is the first result",
            "extra": "property"
        },
        {
            "name": "result 2",
            "description": "tqbf"
        },
        {
            "name": "result 3",
            "description": "jotlz"
        }
    ]
}

调用端点 /test/testserialize 后,我的应用程序抛出此错误

java.lang.ClassCastException: java.util.LinkedHashMap 不能被强制转换 到 com.testapp.entity.TestResult

现在,如果我返回并将 TestSearch 类更新为:

public class TestSearch {

    private String count;
    private List<TestResult> results;

    public String getCount() {
        return count;
    }

    public void setCount(String count) {
        this.count = count;
    }

    public List<TestResult> getResults() {
        return results;
    }

    public void setResults(List<TestResult> results) {
        this.results = results;
    }
}

我得到了我期望的结果:

[
    {
        "name": "new value",
        "description": "this is the first result"
    },
    {
        "name": "new value",
        "description": "tqbf"
    },
    {
        "name": "new value",
        "description": "jotlz"
    }
]

【问题讨论】:

  • 你试过这个教程吗?? blog.bdoughan.com/2012/11/…
  • @Rohan 我还没有看到这个,但是当我在寻找 Jackson 和 JSON 时,我确实注意到它是针对 JaxB 和 XML 的。研究与 @XmlAnyElement 等价的东西可能是一个很好的起点,谢谢

标签: java json spring spring-boot jackson


【解决方案1】:

getForObject函数内部的getClass()方法看不到类型

要解决这个问题,请使用 ParameterizedTypeReference

    TestSearch<TestResult> testSearch = new RestTemplate().exchange(
            "http://localhost:8957/test/json", 
            HttpMethod.GET, 
            null, 
            new ParameterizedTypeReference<TestSearch<TestResult>>() {}).getBody();

我终于找到了一个恰好有 6 年历史的解决方案: Generics with Spring RESTTemplate

【讨论】:

    【解决方案2】:

    您需要为您使用的每个泛型类型创建一个 TypeReference 对象,并将其用于反序列化。例如,

               ObjectMapper mapper = new ObjectMapper();
    
                Map<String, Object> map = new HashMap<String, Object>();
    
                // convert JSON string to Map
                map = mapper.readValue(json, new TypeReference<Map<String, String>>(){});
    

    在您的情况下,您必须为

    创建类型引用
       public List<T> getResults()
    

    如果您需要其他帮助,请告诉我。

    【讨论】:

    • 谢谢,实际上我只是在 RestTemplate 交换方法中使用 ParameterizedTypeReference 解决了这个问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-13
    • 2020-12-02
    • 1970-01-01
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多