使用spring boot将JSON反序列化为带有通用对象列表的POJO

时间:2017-12-19 16:42:05

标签: java json spring spring-boot jackson

我正在尝试反序列化搜索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"
    }
]

2 个答案:

答案 0 :(得分:1)

您需要为您使用的每个泛型类型创建一个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()

如果您需要其他帮助,请与我们联系。

答案 1 :(得分: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