早上好!
我有一个JSON字符串,如下所示:
{
"StatusCode":0,
"Message":null,
"ExecutionTime":0,
"ResponseData":[
{"Name":"name1","SiteId":"1234","Type":"Type1","X":"1234567","Y":"123456"},
{"Name":"Name2","SiteId":"2134","Type":"Type2","X":"1234567","Y":"1234567"},
{"Name":"Name3","SiteId":"3241","Type":"Type3","X":"1234567","Y":"1234567"},
{"Name":"Name4","SiteId":"4123","Type":"Type4","X":"123456","Y":"123456"}
]
}
我想创建一个可以检索X
和Y
值的对象。
我一直在尝试使用Jackson序列化JSON字符串,但没有成功。我为杰克逊创建了两个额外的课程。顶层的一个类StatusCode
,Message
,ExecutionTime
和ResponseData
看起来像
public class PL {
private Long statusCode;
private String executionTime;
private String message;
private ResponseData responseData;
public PL(){
}
public void setStatusCode(Long statusCode){
this.statusCode = statusCode;
}
public Long getStatusCode(){
return this.statusCode;
}
public void setExecutionTime(String executionTime){
this.executionTime = executionTime;
}
public String getExecutionTime(){
return this.executionTime;
}
public void setMessage(String message){
this.message = message;
}
public String getMessage(){
return this.message;
}
public void setResponseData(ResponseData responseData){
this.responseData = responseData;
}
public ResponseData getResponseData(){
return this.responseData;
}
}
将ReponseData
作为对象返回,然后我有另一个用于序列化ResponseData
的类,看起来像
public class ResponseData {
private String name;
private String siteId;
private String type;
private String x;
private String y;
public ResponseData(){
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setSiteId(String siteId){
this.siteId = siteId;
}
public String getSiteId(){
return this.siteId;
}
public void setType(String type){
this.type = type;
}
public String setType(){
return this.type;
}
public void setX(String x){
this.x = x;
}
public String getX(){
return this.x;
}
public void setY(String y){
this.y = y;
}
public String getY(){
return this.y;
}
}
然后我用
创建ObjectMapper
private final static ObjectMapper mapper = new ObjectMapper();
并尝试使用
读取值ResponseData e = mapper.readValue(result.toString(), ResponseData.class);
并最终得到例外
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:无法识别的字段“StatusCode”(类MyClass.ResponseData),未标记为可忽略(5个已知属性:“x”,“y”,“siteId”,“name “,”“类型”])
好像它无法解析第一个条目StatusMessage
。即使我删除第二个类并且只尝试解析前面的四个条目,我将ResponseData
作为String
返回,我仍然会得到相同的异常。
答案 0 :(得分:3)
首先,在PL
中,您应该拥有List<ResponseData>
而不是简单的ResponseData
属性。如您所见,在JSON中,ResponseData
是一个数组"ResponseData":[...]
,因此它将被反序列化为List
。列表中的每个元素都是您定义的ResponseData
对象。
然后你遇到一个案例问题,你在JSON中的大写字母在你的类属性中没有。您可以使用@JsonProperty
(See API)注释来解决此问题:
class PL {
@JsonProperty("StatusCode")
private Long statusCode;
@JsonProperty("ExecutionTime")
private String executionTime;
@JsonProperty("Message")
private String message;
@JsonProperty("ResponseData")
private List<ResponseData> responseDatas;
public PL(){
}
// getters/Setters
}
class ResponseData {
@JsonProperty("Name")
private String name;
@JsonProperty("SiteId")
private String siteId;
@JsonProperty("Type")
private String type;
@JsonProperty("X")
private String x;
@JsonProperty("Y")
private String y;
public ResponseData(){
}
// getters/Setters
}
然后将您的JSON读作PL
对象,如下所示:
ObjectMapper mapper = new ObjectMapper();
PL pl = mapper.readValue(json, PL.class);
for(ResponseData rd : pl.getResponseDatas()) {
System.out.println(rd.getX());
System.out.println(rd.getY());
}
输出:
1234567
123456
1234567
1234567
1234567
1234567
123456
123456
答案 1 :(得分:2)
这很简单。使用类的组合定义响应结构。不幸的是在JSON中使用大写字段,开箱即用需要Java DTO中的大写字段名称。通过使用ObjectMapper
上的 ACCEPT_CASE_INSENSITIVE_PROPERTIES 修饰符或通过注释具有相应名称的字段,可以轻松地将这些名称映射到传统的低案例名称。我更喜欢ObjectMapper
上的属性,因为它使DTO独立于序列化代码,并且此技术在下面的测试中使用(测试为绿色):
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public class TestDeserialization50386188 {
public static class Response {
public static class ResponseDataType {
public String name;
public String siteId;
public String type;
public long x;
public long y;
}
public int statusCode;
public String message;
public long executionTime;
public List<ResponseDataType> ResponseData = new ArrayList<>();
}
private static final String data = "{\"StatusCode\":0,\"Message\":null,\"ExecutionTime\":0,\"ResponseData\":[{\"Name\":\"name1\",\"SiteId\":\"1234\",\"Type\":\"Type1\",\"X\":\"1234567\",\"Y\":\"123456\"},{\"Name\":\"Name2\",\"SiteId\":\"2134\",\"Type\":\"Type2\",\"X\":\"1234567\",\"Y\":\"1234567\"},{\"Name\":\"Name3\",\"SiteId\":\"3241\",\"Type\":\"Type3\",\"X\":\"1234567\",\"Y\":\"1234567\"},{\"Name\":\"Name4\",\"SiteId\":\"4123\",\"Type\":\"Type4\",\"X\":\"123456\",\"Y\":\"123456\"}]}";
@Test
public void deserialize_response_withJackson_ok() throws IOException {
ObjectMapper mapper = new ObjectMapper()
.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
Response response = mapper.readValue(data, Response.class);
assertEquals(4, response.ResponseData.size());
assertEquals(1234567, response.ResponseData.get(2).x);
assertEquals(1234567, response.ResponseData.get(2).y);
}
}
您在this dedicated GitHub repo上找到包含可执行测试的项目。
Bob叔叔的"Clean Code" book并不真正推荐过度使用Java中常见的getter和setter for DTOs Response
类。如果你愿意,你仍然可以用吸气剂/固定剂对替换所有公共区域,但是清晰度会受到影响而没有明显的质量提升。
答案 2 :(得分:1)
使用List接收数组。
<a href="?q={{ request.GET.q }}&page={{ page_obj.previous_page_number }}">
它将自动完成所有操作。