2017-02-23 150 views
2

Jackson JSON - 从嵌套数组中提取数据


注意:我已经重写了这个问题,请问这事先是否过时,我不知道如何解决此问题。


我目前正试图从RESTful API反序列化数据到POJO类。 API的每种方法都返回相同的响应结构,实际结果取决于方法具有不同的结构。我希望能够将每个方法的结果映射到它自己的POJO类。

两个示例JSON响应具有此结构,一个返回一个对象数组,其中另一个返回一系列属性。

在这种情况下,'result'中的每个JSON对象都应该被反序列化到它自己的POJO实例中。

{ 
    "success" : true, 
    "message" : "", 
    "result" : [{ 
      "Frequency" : 0.25000 
      "Range" : 15.6 
     }, { 
      "Frequency" : 0.12500 
      "Range" : 25.1 
     }, { 
      "Frequency" : 0.00750 
      "Range" : 56.0 
     } 
    ] 
} 

在这种情况下,'result'是对象,应映射到单个POJO实例上。

{ 
    "success" : true, 
    "message" : "", 
    "result" : { 
     "Bid" : 2.05670368, 
     "Ask" : 3.35579531, 
     "Last" : 3.35579531 
    } 
} 

这将是与前面的示例不同的类,因为它是来自不同API方法的响应。 我只是想提取结果,任何回应都不需要成功和消息。

+0

这是令人困惑的究竟是什么努力实现?为你创建一个POJO类吗?阐述你的问题! – Coder

+0

我想用包含在结果数组中的数据来填充POJO实例。结果可以包含一个单个对象或一个对象数组,因此默认对象映射器正在努力实现这一点。需要哪些注释/方法? – Flemingjp

+0

@Coder我已经重写了这个问题,因为它对于准确的响应过于宽泛 – Flemingjp

回答

1

由于您的results响应是动态的,我建议您不要在反序列化中包含您的results对象。将下面的代码包含在你的POJO类中,它会执行删除操作。

@JsonIgnore 
private Map<String, Object> additionalProperties = new HashMap<String, Object>(); 

@JsonAnyGetter 
public Map<String, Object> getAdditionalProperties() { 
return this.additionalProperties; 
} 

@JsonAnySetter 
public void setAdditionalProperty(String name, Object value) { 
this.additionalProperties.put(name, value); 
} 

现在Map名为additionalProperties将包含你还没有尝试过的父对象捕捉(在这种情况下,将有你的results对象)的任何其他对象。它根据您的响应存储Objectlist of Objects,您可以通过键值results访问它。

正如建议使用泛型类型FlemingJp似乎是一个非常可行的解决方案,因此我在这个答案中包含该部分。

公共类响应{

private boolean success; 
    private String message; 
    private T result; 

    public T getResult() { 
     return result; 
    } 

    public String getMessage() { 
     return message; 
    } 

    public boolean getSuccess() { 
     return success; 
    } 
} 

使用示例

ObjectMapper objectMapper = new ObjectMapper(); 

// When the result is one object 
Response<DistanceStat> res = objectMapper.readValue(data, new TypeReference<Response<DistanceStat>>() {}); 

// For a collection of objects under result 
Response<Collection<DistanceStat>> res = objectMapper.readValue(data, new TypeReference<Response<Collection<DistanceStat>>>() {}); 

编辑

可以在杰克逊反序列化如下:

ObjectMapper mapper = new ObjectMapper(); 
String jsonInString //which contains your json data in string 
ParentNode parentNode = mapper.readValue(jsonInString, ParentNode.class); 

PraentNode是你的父类。

编辑2

Note:这是非常具体的,以你的情况。

这些是你将需要的POJO类,父类,你要反序列化

import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import com.fasterxml.jackson.annotation.JsonAnyGetter; 
import com.fasterxml.jackson.annotation.JsonAnySetter; 
import com.fasterxml.jackson.annotation.JsonIgnore; 
import com.fasterxml.jackson.annotation.JsonInclude; 
import com.fasterxml.jackson.annotation.JsonProperty; 
import com.fasterxml.jackson.annotation.JsonPropertyOrder; 

@JsonInclude(JsonInclude.Include.NON_NULL) 
@JsonPropertyOrder({ 
"success", 
"message" 
}) 
public class Example { 

@JsonProperty("success") 
private Boolean success; 
@JsonProperty("message") 
private String message; 

@JsonIgnore 
private Map<String, Object> additionalProperties = new HashMap<String, Object>(); 

@JsonProperty("success") 
public Boolean getSuccess() { 
return success; 
} 

@JsonProperty("success") 
public void setSuccess(Boolean success) { 
this.success = success; 
} 

@JsonProperty("message") 
public String getMessage() { 
return message; 
} 

@JsonProperty("message") 
public void setMessage(String message) { 
this.message = message; 
} 

@JsonAnyGetter 
public Map<String, Object> getAdditionalProperties() { 
return this.additionalProperties; 
} 

@JsonAnySetter 
public void setAdditionalProperty(String name, Object value) { 
this.additionalProperties.put(name, value); 
} 

} 

我故意不包括在这里Result类。现在,无论Result响应你将存储在名为Mapadditional propertiesobject可以是list<Result>或类Result

现在你有两个结构为Result对象。您可以将它们存储在相同的POJO中。所以让我们为每个结构构建两个不同的POJO类。

Result1.java

import java.util.HashMap; 
import java.util.Map; 
import com.fasterxml.jackson.annotation.JsonAnyGetter; 
import com.fasterxml.jackson.annotation.JsonAnySetter; 
import com.fasterxml.jackson.annotation.JsonIgnore; 
import com.fasterxml.jackson.annotation.JsonInclude; 
import com.fasterxml.jackson.annotation.JsonProperty; 
import com.fasterxml.jackson.annotation.JsonPropertyOrder; 

@JsonInclude(JsonInclude.Include.NON_NULL) 
@JsonPropertyOrder({ 
"Frequency", 
"Range" 
}) 
public class Result1 { 

@JsonProperty("Frequency") 
private Double frequency; 
@JsonProperty("Range") 
private Double range; 
@JsonIgnore 
private Map<String, Object> additionalProperties = new HashMap<String, Object>(); 

@JsonProperty("Frequency") 
public Double getFrequency() { 
return frequency; 
} 

@JsonProperty("Frequency") 
public void setFrequency(Double frequency) { 
this.frequency = frequency; 
} 

@JsonProperty("Range") 
public Double getRange() { 
return range; 
} 

@JsonProperty("Range") 
public void setRange(Double range) { 
this.range = range; 
} 

@JsonAnyGetter 
public Map<String, Object> getAdditionalProperties() { 
return this.additionalProperties; 
} 

@JsonAnySetter 
public void setAdditionalProperty(String name, Object value) { 
this.additionalProperties.put(name, value); 
} 

} 

Result2.java:

import java.util.HashMap; 
import java.util.Map; 
import com.fasterxml.jackson.annotation.JsonAnyGetter; 
import com.fasterxml.jackson.annotation.JsonAnySetter; 
import com.fasterxml.jackson.annotation.JsonIgnore; 
import com.fasterxml.jackson.annotation.JsonInclude; 
import com.fasterxml.jackson.annotation.JsonProperty; 
import com.fasterxml.jackson.annotation.JsonPropertyOrder; 

@JsonInclude(JsonInclude.Include.NON_NULL) 
@JsonPropertyOrder({ 
"Bid", 
"Ask", 
"Last" 
}) 
public class Result2 { 

@JsonProperty("Bid") 
private Double bid; 
@JsonProperty("Ask") 
private Double ask; 
@JsonProperty("Last") 
private Double last; 
@JsonIgnore 
private Map<String, Object> additionalProperties = new HashMap<String, Object>(); 

@JsonProperty("Bid") 
public Double getBid() { 
return bid; 
} 

@JsonProperty("Bid") 
public void setBid(Double bid) { 
this.bid = bid; 
} 

@JsonProperty("Ask") 
public Double getAsk() { 
return ask; 
} 

@JsonProperty("Ask") 
public void setAsk(Double ask) { 
this.ask = ask; 
} 

@JsonProperty("Last") 
public Double getLast() { 
return last; 
} 

@JsonProperty("Last") 
public void setLast(Double last) { 
this.last = last; 
} 

@JsonAnyGetter 
public Map<String, Object> getAdditionalProperties() { 
return this.additionalProperties; 
} 

@JsonAnySetter 
public void setAdditionalProperty(String name, Object value) { 
this.additionalProperties.put(name, value); 
} 

} 

现在你使用下面的代码段反序列化JSON:

ObjectMapper mapper = new ObjectMapper(); 
    String jsonInString //which contains your json data in string 
    Example example= mapper.readValue(jsonInString, Example.class); 

来了棘手的部分,现在您的地图包含Results响应,但我们不确定它是否是对象列表或目的。

现在得到Results我们将首先尝试确定它是否是一个集合(如列表是一个集合),这将有助于我们识别。

Object resultObject = example.getAdditionalProperties().getKey("results"); 

if (resultObject instanceof Collection<?>){ 

List<Result1> results=resultObject; 
} 

else{ 

Result2 results=resultObject; 

} 

希望这可以解决您的问题!

让我知道你是否需要澄清任何事情!

+0

结果属性varys来自不同的api方法,而不是从请求到同一方法的请求。我试图在我的帖子中澄清这一点。每种方法我都会有不同的POJO,但是所有的都有相同的响应结构,我想要处理 – Flemingjp

+0

,所以您只需查看如何使用jackson进行反序列化? – Coder

+0

我想要肯定。 – Flemingjp

1

我设法解决了我的问题。我按照编码器的建议创建了一个ParentNode。这允许任何类型甚至集合都在结果中。


响应等级

public class Response<T> { 

    private boolean success; 
    private String message; 
    private T result; 

    public T getResult() { 
     return result; 
    } 

    public String getMessage() { 
     return message; 
    } 

    public boolean getSuccess() { 
     return success; 
    } 
} 


使用示例

ObjectMapper objectMapper = new ObjectMapper(); 

// When the result is one object 
Response<DistanceStat> res = objectMapper.readValue(data, new TypeReference<Response<DistanceStat>>() {}); 

// For a collection of objects under result 
Response<Collection<DistanceStat>> res = objectMapper.readValue(data, new TypeReference<Response<Collection<DistanceStat>>>() {}); 

这是一个接近一个完美的解决方案,现在我正在寻找,现在将是有益的避免在第二个使用示例中使用三重类型定义。

注:我接受编码器的答案,因为它导致这种解决方案。