【问题标题】:How RestTemplate parse responseRestTemplate 如何解析响应
【发布时间】:2016-07-13 08:03:21
【问题描述】:

在开发spring REST Client时,出现一个问题:

  1. 我有下一个 json:


{
 "return": [
 {
    "admin": false,
    "alias": "",
    "email": "",
    "emailId": {"value": 0},
    "groups": [],
    "id": {"value": 1},
    "locked": false,
    "loggedInCount": 0,
    "master": true,
    "sms": "",
    "smsId": {"value": 0},
    "type": "POWER",
    "username": "NGCP"
 },
 {
    "admin": false,
    "alias": "",
    "email": "",
    "emailId": {"value": 0},
    "groups": [{"value": 2}],
    "id": {"value": 3},
    "locked": false,
    "loggedInCount": 0,
    "master": false,
    "sms": "",
    "smsId": {"value": 0},
    "type": "POWER",
    "username": "POLICY"
 }
        ]
}

保存用户的模型类:

@JsonIgnoreProperties(ignoreUnknown = true)
public class User {

   public User(){

   }

   private boolean admin;

   private String alias;

   private String email;

   private String emailId;

   private ArrayList<String> groups;

   private String id;

   private boolean locked;

   private int loggedInCount;

   private boolean master;

   private String sms;

   private String smsId;

   private String type;

   private String userName;

//getter and setters
}

现在我正在使用“RestTemplate”来获取结果。

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<User[]> response = restTemplate.exchange(URL_GET,HttpMethod.GET,request, User[].class);

并得到错误。我知道这是因为主键是“结果”,但我可以指定 restTemplate 应该从哪里解析这个 JSON 吗?

并且可以在文件上注明喜欢“emailId”以获得直接价值?一些模板?

【问题讨论】:

  • “获得直接价值”是什么意思?
  • 在这个文件中,我再次拥有一对“key - value”。我只需要取值
  • 错误是什么? “主键是结果”是什么意思?
  • @Michael Wiles 问题已经解决,查看答案。当我谈论“主键”时,我的意思是来自 json 的第一个键。错误是因为我没有注释更正我的模型类。

标签: java spring pojo resttemplate


【解决方案1】:
  1. 至于“主键是结果”:

    一个。如果您只处理一种此类 Web 服务,我将为实际有效负载创建一个包装类:

    public class Return{
        // Class property cannot be called "return" because it is Java reserved name.
        @JsonProperty("return")
        private User[] array;
        .... getter and setter
    }
    

    b.如果您处理实际有效负载位于“返回”字段中的多个 Web 服务,我将创建一个通用包装类:

    public class Return<T>{
        // Class property cannot be called "return" because it is Java reserved name.
        @JsonProperty("return")
        private T[] array;
        .... getter and setter
    }
    

    致电RestRemplate:

    ResponseEntity<Return<User>> response = restTemplate.exchange(URL_GET, 
            HttpMethod.GET, request, new ParameterizedTypeReference<Return<User>>(){});
    User[] usersArray = response2.getBody().getArray();
    
  2. 对于名为“value”的 JSON 属性中的属性值,我将创建两个自定义 JsonDeserializer(s):一个用于单个值,一个用于值数组,并在每个属性适用的地方用 @JsonDeserialize 注释:

    单值反序列化器:

    public class StringValueDeserializer  extends JsonDeserializer<String>{
    
        @Override
        public String deserialize(JsonParser parser, DeserializationContext ctxt)
                throws IOException, JsonProcessingException {
            ObjectCodec codec = parser.getCodec();
            TreeNode node = codec.readTree(parser);
            JsonNode value = (JsonNode)node.get("value");
    
            if (value != null){
                return value.asText();
            }
            return null;
        }
    }
    

    值数组解构器:

    public class StringArrayValueDeserializer  extends JsonDeserializer<List<String>>{
    
        @Override
        public List<String> deserialize(JsonParser parser, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
    
            List<String> ret = new ArrayList<>();
    
            ObjectCodec codec = parser.getCodec();
            TreeNode node = codec.readTree(parser);
    
            if (node.isArray()){
                for (JsonNode n : (ArrayNode)node){
                    JsonNode value = n.get("value");
                    if (value != null){
                        ret.add(value.asText());
                    }
                }
            }
            return ret;
        }
    }
    

    你是新来的User.class:

    public class User {
    
        private boolean admin;
    
        private String alias;
    
        private String email;
    
        @JsonDeserialize(using = StringValueDeserializer.class)
        private String emailId;
    
        @JsonDeserialize(using = StringArrayValueDeserializer.class)
        private ArrayList<String> groups;
    
        @JsonDeserialize(using = StringValueDeserializer.class)
        private String id;
    
        private boolean locked;
    
        private int loggedInCount;
    
        private boolean master;
    
        private String sms;
    
        @JsonDeserialize(using = StringValueDeserializer.class)
        private String smsId;
    
        private String type;
    
        private String username;
        .... getter and setter
    }
    

祝你好运!

【讨论】:

    【解决方案2】:

    你也可以使用JsonPath库来浏览json:

    String json =  restTemplate.exchange(URL_GET,HttpMethod.GET,request, String.class);
    DocumentContext document = JsonPath.parse(content, json);
    List<User> users = document.read("$.return.*", new TypeRef<List<User>>() {});
    

    【讨论】:

      【解决方案3】:

      您可以使用注释 @JsonRootName 来指定响应中的根元素。所以试试这个:

      @JsonIgnoreProperties(ignoreUnknown = true)
      @JsonRootName(value ="result")
      public class User {
      
         public User(){
      
         }
      
         private boolean admin;
      
         ....
      }
      

      【讨论】:

      • 如果你使用 User 对象来创建或更新 json 根名称注释会有什么影响?或者这仅用于读取(获取)数据。
      猜你喜欢
      • 2014-04-16
      • 1970-01-01
      • 2016-03-28
      • 1970-01-01
      • 2016-02-02
      • 2020-10-07
      • 1970-01-01
      • 2018-02-06
      相关资源
      最近更新 更多