【问题标题】:Jackson JSON - Extract data from nested arrayJackson JSON - 从嵌套数组中提取数据
【发布时间】:2017-02-23 16:49:12
【问题描述】:


注意:我已经重写了这个问题,问它事先过于笼统,我不知道如何解决这个问题。

我目前正在尝试将 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
        }
    ]
}

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

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

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

【问题讨论】:

  • 到底想达到什么目的令人困惑?创建 POJO 类是否适合您?详细说明您的问题!
  • 我想用结果数组中包含的数据填充 POJO 实例。结果可以包含一个对象或一组对象,因此默认对象映射器很难实现这一点。需要哪些注释/方法?
  • @Coder 我已经重写了这个问题,因为它太模糊了,无法准确回答
  • 我已经更新了我的回复@Flemingjp

标签: java arrays json jackson


【解决方案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 所建议的,对于这个问题,使用泛型类型似乎是一个非常可行的解决方案,所以我在这个答案中也包括了这部分。

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

编辑

你可以在jackson中反序列化如下:

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 propertiesMap 中,作为 object 可以是 list&lt;Result&gt; 或类 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;

}

希望这能解决您的问题!

如果您需要澄清任何事情,请告诉我!

【讨论】:

  • result 属性因不同的 api 方法而异,而不是因同一方法的请求而异。我试图在我的帖子中澄清这一点。我将为每种方法使用不同的 POJO,但它们都具有我想要处理的相同响应结构
  • 所以您只是想了解如何使用 jackson 进行反序列化?
  • 我想是的。
  • 是的。来自 Http GET 请求
  • @Flemingjp 解决了这个问题?你也在寻找 pojo 课程吗?
【解决方案2】:

我设法解决了我的问题。我按照 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 的回答,因为它导致了这个解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-28
    • 1970-01-01
    • 2022-07-12
    相关资源
    最近更新 更多