繁体   English   中英

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

[英]Jackson JSON - Extract data from nested array


注意:我已经改写了这个问题,询问它是否事先过于庞大,并且我不知道如何解决此问题。


我目前正在尝试将来自RESTful API的数据反序列化为POJO类。 API的每种方法都返回相同的响应结构,实际结果根据方法的不同而变化。 我希望能够将每个方法的结果映射到其自己的POJO类。

样本JSON响应中有两个具有这种结构,一个返回对象数组,另一个返回一系列属性。

在这种情况下,应将“结果”中的每个JSON对象反序列化为它自己的POJO实例。

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

在这种情况下,“结果”是对象,应映射到单个POJO实例。

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

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

由于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对象)。 它根据您的响应存储ObjectObject list of Objects您可以使用键值results访问它。

正如FlemingJp所建议的那样,对于该问题,使用泛型类型似乎是一个非常可行的解决方案,因此我也在此答案中也包括了这一部分。

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>>>() {});

编辑

您可以按照以下步骤在杰克逊中反序列化:

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响应,都将作为additional properties object存储在Map名为additional propertiesobject ,该object可以是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;

}

希望这能解决您的问题!

让我知道您是否需要任何澄清!

我设法解决了我的问题。 我按照Coder的建议使用通用类型创建了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>>>() {}); 

这与我现在正在寻找的一种优雅的解决方案非常接近,现在将有助于避免第二个用法示例中的三重类型定义。

注意:我接受Coder的回答,因为它会导致此解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM