[英]Mapping a dynamic json object field in Jackson?
I have json objects in the following schema: 我在以下架构中有json对象:
{
name: "foo",
timestamp: 1475840608763,
payload:
{
foo: "bar"
}
}
Here, the payload
field contains an embedded json object, and the schema of this object is dynamic, and different each time. 这里,
payload
字段包含一个嵌入的json对象,该对象的模式是动态的,每次都不同。
The payload
object is the raw output obtained from different API services, and different methods of different API services. payload
对象是从不同API服务获得的原始输出,以及不同API服务的不同方法。 It isn't possible to map it to all possible values. 无法将其映射到所有可能的值。
Is it possible to have a java class such as the following: 是否可以拥有一个java类,如下所示:
public class Event
{
public String name;
public long timestamp;
public JsonObject payload;
}
Or something along those lines, so I can receive the basic schema and process it, then send it to the relevant class which will convert payload
to its appropriate expected class? 或者沿着这些方向的东西,所以我可以接收基本模式并处理它,然后将它发送到相关的类,它将
payload
转换为适当的预期类?
JsonNode
JsonNode
You could use JsonNode
from the com.fasterxml.jackson.databind
package: 你可以使用
JsonNode
从com.fasterxml.jackson.databind
包:
public class Event {
public String name;
public long timestamp;
public JsonNode payload;
// Getters and setters
}
Then parse it using: 然后使用以下方法解析它:
String json = "{\"name\":\"foo\",\"timestamp\":1475840608763,"
+ "\"payload\":{\"foo\":\"bar\"}}";
ObjectMapper mapper = new ObjectMapper();
Event event = mapper.readValue(json, Event.class);
JsonNode
to a POJO JsonNode
映射到POJO Consider, for example, you want to map the JsonNode
instance to the following class: 例如,考虑您要将
JsonNode
实例映射到以下类:
public class Payload {
private String foo;
// Getters and setters
}
It can be achieved with the following piece of code: 它可以通过以下代码实现:
Payload payload = mapper.treeToValue(event.getPayload(), Payload.class);
Map<String, Object>
Map<String, Object>
Depending on your requirements, you could use a Map<String, Object>
instead of JsonNode
: 根据您的要求,您可以使用
Map<String, Object>
而不是JsonNode
:
public class Event {
public String name;
public long timestamp;
public Map<String, Object> payload;
// Getters and setters
}
If you need to convert a Map<String, Object>
to a POJO, use: 如果需要将
Map<String, Object>
转换为POJO,请使用:
Payload payload = mapper.convertValue(event.getPayload(), Payload.class);
According to the Jackson documentation , the convertValue()
method is functionally similar to first serializing given value into JSON, and then binding JSON data into value of given type, but should be more efficient since full serialization does not (need to) occur. 根据Jackson 文档 ,
convertValue()
方法在功能上类似于首先将给定值序列化为JSON,然后将JSON数据绑定到给定类型的值,但应该更高效,因为完全序列化不会(需要)发生。 However, same converters (serializers and deserializers) will be used as for data binding, meaning same object mapper configuration works. 但是,相同的转换器(序列化器和反序列化器)将用于数据绑定,这意味着相同的对象映射器配置工作。
Does this help? 这有帮助吗?
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
public class Payload {
private final Map<String, Object> other = new HashMap<>();
@JsonAnyGetter
public Map<String, Object> any() {
return other;
}
@JsonAnySetter
public void set(final String name, final Object value) {
other.put(name, value);
}
public Map<String, Object> getOther() {
return other;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + ((other == null) ? 0 : other.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Payload)) {
return false;
}
Payload other = (Payload) obj;
if (this.other == null) {
if (other.other != null) {
return false;
}
} else if (!this.other.equals(other.other)) {
return false;
}
return true;
}
@Override
public String toString() {
return "Payload [other=" + other + "]";
}
}
Then this owning class 然后是这个拥有的班级
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Outer {
private final String name;
private final long timestamp;
private final Payload payload;
@JsonCreator
public Outer(@JsonProperty("name") final String name, @JsonProperty("timestamp") final long timestamp, @JsonProperty("payload") final Payload payload) {
super();
this.name = name;
this.timestamp = timestamp;
this.payload = payload;
}
public String getName() {
return name;
}
public long getTimestamp() {
return timestamp;
}
public Payload getPayload() {
return payload;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + ((name == null) ? 0 : name.hashCode());
result = (prime * result) + ((payload == null) ? 0 : payload.hashCode());
result = (prime * result) + (int) (timestamp ^ (timestamp >>> 32));
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Outer)) {
return false;
}
Outer other = (Outer) obj;
if (name == null) {
if (other.name != null) {
return false;
}
} else if (!name.equals(other.name)) {
return false;
}
if (payload == null) {
if (other.payload != null) {
return false;
}
} else if (!payload.equals(other.payload)) {
return false;
}
if (timestamp != other.timestamp) {
return false;
}
return true;
}
@Override
public String toString() {
return "Outer [name=" + name + ", timestamp=" + timestamp + ", payload=" + payload + "]";
}
}
Then to test 然后去测试
public class Main {
private static final ObjectMapper mapper = new ObjectMapper();
public static void main(final String... args) throws JsonParseException, JsonMappingException, IOException {
final Outer outer = mapper.readValue(new File("test.json"), Outer.class);
System.out.println(outer);
}
}
Gives console output of 提供控制台输出
Outer [name=foo, timestamp=1475840608763, payload=Payload [other={foo=bar}]]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.