【问题标题】:Spring RestTemplate getForObject Map<String, POJO> class mappingSpring RestTemplate getForObject Map<String, POJO> 类映射
【发布时间】:2020-07-23 05:38:12
【问题描述】:

我有以下 POJO:

class TestPojo {

    private Long testId = null;
    private String testString = null;
    private boolean testBoolean = false;
    private Float testFloat = null;
    private int testInt = 0;
    private Collection<String> testCollection = new TreeSet();

    Long getTestId() {
        return testId;
    }

    void setTestId(Long testId) {
        this.testId = testId;
    }

    String getTestString() {
        return testString;
    }

    void setTestString(String testString) {
        this.testString = testString;
    }

    boolean getTestBoolean() {
        return testBoolean;
    }

    void setTestBoolean(boolean testBoolean) {
        this.testBoolean = testBoolean;
    }

    Float getTestFloat() {
        return testFloat;
    }

    void setTestFloat(Float testFloat) {
        this.testFloat = testFloat;
    }

    int getTestInt() {
        return testInt;
    }

    void setTestInt(int testInt) {
        this.testInt = testInt;
    }

    Collection<String> getTestCollection() {
        return testCollection;
    }

    void setTestCollection(Collection<String> testCollection) {
        this.testCollection = testCollection;
    }
}

我有两个 REST API 响应,一个返回 JSON 格式的单个 TestPojo 实例:

{
  "testId": 1,
  "testString": "testStringA",
  "testBoolean": false,
  "testFloat": 1.0,
  "testInt": 1,
  "testCollection": [
    "testCollectionA",
    "testCollectionB"
  ]
}

另一个 REST API 响应返回多个 TestPojo 的映射:

{
  "TestPojoA": {
    "testId": 1,
    "testString": "testStringA",
    "testBoolean": false,
    "testFloat": 1.0,
    "testInt": 1,
    "testCollection": [
      "testCollectionA",
      "testCollectionB"
    ]
  },
  "TestPojoB": {
    "testId": 2,
    "testString": "testStringB",
    "testBoolean": true,
    "testFloat": 1.1,
    "testInt": 2,
    "testCollection": [
      "testCollectionC",
      "testCollectionB"
    ]
  }
}

带有 MappingJackson2HttpMessageConverter 的我的 Rest 模板正确返回第一个 JSON 的 POJO:

RestTemplate restTemplate = new RestTemplate();
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
TestPojo testPojo = restTemplate.getForObject("http://127.0.0.1:8081/test/getPojoInstance", TestPojo.class);

但是,我无法让地图中的 POJO 正确转换?我尝试了各种方法,我认为以下方法可行,但这只是返回一个包含两个字符串值而不是 String 和 POJO 的映射:

RestTemplate restTemplate = new RestTemplate();
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
Map<String, TestPojo> testPojoMap = restTemplate.getForObject("http://127.0.0.1:8081/test/getPojoMap", Map<String, TestPojo>.class);

我知道我可以在收到响应后将我的地图中的字符串值转换为 TestPojo,但我只是好奇这是不是我一开始做的不对?

【问题讨论】:

    标签: java rest spring-mvc jackson


    【解决方案1】:

    我认为是getForObject的类型问题,我建议使用exchange方法

    ResponseEntity<Map<String, TestPojo>> response = template.exchange("http://127.0.0.1:8081/test/getPojoMap", 
             HttpMethod.GET, null, new ParameterizedTypeReference<Map<String, TestPojo>>() {
    });
    
    Map<String, TestPojo> body = response.getBody();
    

    【讨论】:

    • 谢谢@Deadpool,我已经试过了。不幸的是,这也不起作用。收到以下错误:Could not read document: Can not instantiate value of type [simple type, class com.complianceandrisks.c2png.pogo.TestPojo] from String value ('{"testId": 2, "testString": "testStringB", "testBoolean": true, "testFloat": 1.1, "testInt": 2, "testCollection": ["testCollectionC", "testCollectionB"]}'); no single-String constructor/factory method at [Source: java.io.PushbackInputStream@40b4c714; line: 1, column: 2]
    【解决方案2】:

    RestTemplate 可以像您一样将 JSON 反序列化为 java.util.Map 而不是 java.util.Map&lt;String, TestPojo&gt;

    你可以使用Jackson ObjectMapper给TypeReference

    String testPojoMap = restTemplate.getForObject("http://127.0.0.1:8081/test/getPojoMap", String.class);
    ObjectMapper objectMapper = new ObjectMapper();
    Map<String, TestPojo> map = objectMapper.readValue(testPojoMap, new TypeReference<Map<String,TestPojo>>(){});
    

    或者

    不休息模板

    ObjectMapper objectMapper = new ObjectMapper();
    Map<String, TestPojo> map = objectMapper.readValue("http://127.0.0.1:8081/test/getPojoMap", new TypeReference<Map<String,TestPojo>>(){});
    

    【讨论】:

    • 谢谢@Abinash,我知道Jackson ObjectMapper,我现在正在使用它作为解决方法。但是,我试图弄清楚如何使用 Rest Template 来做到这一点。考虑到我已将 MappingJackson2HttpMessageConverter 添加到我的休息模板中,我会认为这会起作用,我只是想知道为什么不是这样。
    猜你喜欢
    • 2014-08-04
    • 2019-12-24
    • 2018-01-16
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 2014-06-25
    • 2018-04-26
    • 2014-04-25
    相关资源
    最近更新 更多