在Jackson中映射动态json对象字段?

我在以下架构中有json对象:

{ name: "foo", timestamp: 1475840608763, payload: { foo: "bar" } } 

这里, payload字段包含一个嵌入的json对象,该对象的模式是动态的,每次都不同。

payload对象是从不同API服务获得的原始输出,以及不同API服务的不同方法。 无法将其映射到所有可能的值。

是否可以拥有一个java类,如下所示:

 public class Event { public String name; public long timestamp; public JsonObject payload; } 

或者沿着那些方向的东西,所以我可以接收基本模式并处理它,然后将它发送到相关的类,它将payload转换为适当的预期类?

使用JsonNode

您可以使用com.fasterxml.jackson.databind包中的com.fasterxml.jackson.databind

 public class Event { public String name; public long timestamp; public JsonNode payload; // Getters and setters } 

然后使用以下方法解析它:

 String json = "{\"name\":\"foo\",\"timestamp\":1475840608763," + "\"payload\":{\"foo\":\"bar\"}}"; ObjectMapper mapper = new ObjectMapper(); Event event = mapper.readValue(json, Event.class); 

JsonNode映射到POJO

例如,考虑您要将JsonNode实例映射到以下类:

 public class Payload { private String foo; // Getters and setters } 

可以使用以下代码实现:

 Payload payload = mapper.treeToValue(event.getPayload(), Payload.class); 

考虑Map

根据您的要求,您可以使用Map而不是JsonNode

 public class Event { public String name; public long timestamp; public Map payload; // Getters and setters } 

如果需要将Map转换为POJO,请使用:

 Payload payload = mapper.convertValue(event.getPayload(), Payload.class); 

根据Jackson 文档 , convertValue()方法在function上类似于首先将给定值序列化为JSON,然后将JSON数据绑定到给定类型的值,但应该更高效,因为完全序列化不会(需要)发生。 但是,相同的转换器(序列化器和反序列化器)将用于数据绑定,这意味着相同的对象映射器配置工作。

这有帮助吗?

 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 other = new HashMap<>(); @JsonAnyGetter public Map any() { return other; } @JsonAnySetter public void set(final String name, final Object value) { other.put(name, value); } public Map 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 + "]"; } } 

然后是这个拥有的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 + "]"; } } 

然后去测试

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

提供控制台输出

 Outer [name=foo, timestamp=1475840608763, payload=Payload [other={foo=bar}]]