Spring RestTemplate 响应中从 JSON 到 Java/POJO 的自定义映射

Posted

技术标签:

【中文标题】Spring RestTemplate 响应中从 JSON 到 Java/POJO 的自定义映射【英文标题】:Custom Mapping from JSON to Java/POJO in Spring RestTemplate response 【发布时间】:2020-02-07 00:26:12 【问题描述】:

我有一个 Spring Boot 应用程序,我在其中使用 RestTemplate 调用 Rest API,我收到以下 JSON 格式的响应:


  "data": [
    
      "id": "1",
      "type": "type1",
      "config": 
        "property1" : "value1",
        "property2" : "value2"
      
    ,
    
      "id": "2",
      "type": "type2",
      "config": 
        "property3" : "value3",
        "property4" : "value4",
        "propArray": [ "element1", "element2"]
      
    
  ]

数组 'data' 中的各个元素有几个不同的结构(上面的 2 个示例),我想将不同的类类型映射到各个元素,这取决于元素 'type' 的值。

例如值'type1'应该映射到类类型'Type1'的对象等等。

我创建了如下类: 我的回应:

public Class MyResponse 
  List<Data> data;
..
  \\getter and setters

数据:

public Interface Data 

类型1:

public Class Type1 implements Data 
  private String property1;

  private String property2;
..
  \\getter and setters

类型2:

public Class Type1 implements Data 
  private String property3;

  private String property4;

  private List<String> propArray;
..
  \\getter and setters

如何映射以上条件结构?

【问题讨论】:

这就是json序列化和反序列化。使用 Jackson tutorials.jenkov.com/java-json/jackson-objectmapper.html 并创建 POJO 使用此站点 jsonschema2pojo.org 【参考方案1】:

我能想到的唯一方法是获取返回值一个字符串,将其转换为 JSONObject 并对其进行处理以创建类的实例。例如,

    String response = restTemplate.<your-uri>
    JSONObject jsonObject = new JSONObject(response);
    if (jsonObject.get(type).equals(type1) 
        Type1 type1 = new Type1();
        // set values
     else if (jsonObject.get(type).equals(type2) 
        Type2 type2 = new Type2()
        // set values
    

但是,这是不可扩展的,如果您要添加越来越多的类型,维护干净的代码将非常困难。

您可以这样做的另一种方法是创建一个通用类并接收作为该类列表的响应。这样Spring-boot/jackson就可以做映射了。同样,您必须添加代码以从这个通用类创建其他类。正如 Sam 在评论中指出的那样,这将是首选,因为 Jackson 比 JSONObject 快。这是示例类的样子,

class Response 
    private Integer id;
    private String type;
    private Map<String, Object> config;

您仍然需要检查类型并映射到相应的类。

如果您可以控制它,我会考虑是否可以重新设计您发送的设计/响应,而不是编写如此混乱的代码。

【讨论】:

JSONObject 最初是作为 java 中 json 的 POC 创建的。与 java json 序列化和反序列化库相比,它的性能最差。强烈推荐使用 Jackson、Gson 等。 我同意,这是我推荐的第二种方法。我将更新答案以包括关于速度的观点。 响应来自第三方产品,因此我们无法控制。我不担心性能,因为这项工作将仅用于部署。类型的数量是有限的,所以我想我可以使用字符串列表,然后使用 JSONObject 手动将字符串映射到调用: public Class MyResponse List data; .. \\getter 和 setter 您能否举一个关于创建“通用”类的第二个选项的示例?因为我不确定您会将数据存储在哪里?作为此类中的 Map,我想? 是的,你是对的。它将是 Map 因为值可以是字符串或数组。我只是用示例类更新我的答案..

以上是关于Spring RestTemplate 响应中从 JSON 到 Java/POJO 的自定义映射的主要内容,如果未能解决你的问题,请参考以下文章

Spring:RestTemplate 响应乱码

Spring:RestTemplate 响应乱码

如何在 Spring RestTemplate 中记录响应?

Spring WebClient与RestTemplate性能对比——响应式Spring的道法

用于 Xml 响应的 Spring RestTemplate POST 方法?

如何使用 Spring RestTemplate 使用 Page<Entity> 响应