在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}]]