java RestTemplate 如何解析响应
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38345893/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How RestTemplate parse response
提问by GVArt
While developing spring REST Client, appear a problem:
在开发spring REST Client时,出现一个问题:
- I have next json:
- 我有下一个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"
}
]
}
Model class to save User:
保存用户的模型类:
@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
}
Now I'm using "RestTemplate" to get result.
现在我使用“RestTemplate”来获得结果。
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<User[]> response = restTemplate.exchange(URL_GET,HttpMethod.GET,request, User[].class);
And get error. I know that is because main key is "result" but can I specify from where should restTemplate parse this JSON?
并得到错误。我知道这是因为主键是“结果”,但我可以指定 restTemplate 应该从哪里解析这个 JSON?
And it's possible to indicate on fileds liks "emailId" to get direct value? some templates?
并且可以在文件上指明喜欢“emailId”以获得直接价值?一些模板?
回答by Michal Foksa
As of the "main key is result":
a. I would create a wrapper class for the actual payload if you deal with just one of this kind of web service:
public class Return{ // Class property cannot be called "return" because it is Java reserved name. @JsonProperty("return") private User[] array; .... getter and setter }
b. If you deal with multiple webservices where actual payload is in "return" field I would create a generic wrapper class :
public class Return<T>{ // Class property cannot be called "return" because it is Java reserved name. @JsonProperty("return") private T[] array; .... getter and setter }
Call to
RestRemplate
:ResponseEntity<Return<User>> response = restTemplate.exchange(URL_GET, HttpMethod.GET, request, new ParameterizedTypeReference<Return<User>>(){}); User[] usersArray = response2.getBody().getArray();
As of the property value in JSON attribute called "value" I would create two custom
JsonDeserializer
(s): one for single value and one for array of values and annotate each property with@JsonDeserialize
where it applies:Single value deserializer:
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; } }
Array of values derializer:
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; } }
Here you are new
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 }
至于“主要关键是结果”:
一个。如果您只处理此类 Web 服务中的一种,我将为实际负载创建一个包装类:
public class Return{ // Class property cannot be called "return" because it is Java reserved name. @JsonProperty("return") private User[] array; .... getter and setter }
湾 如果您处理实际有效负载在“返回”字段中的多个 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();
对于名为“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 }
Good luck!
祝你好运!
回答by romanvintonyak
You can also use the JsonPathlibrary to navigate through json:
您还可以使用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>>() {});
回答by Mohsan Shakir
You can use the annotation @JsonRootName to specify the root element in your response. So try this:
您可以使用注释 @JsonRootName 指定响应中的根元素。所以试试这个:
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonRootName(value ="result")
public class User {
public User(){
}
private boolean admin;
....
}