java 在 Jackson 中映射动态 json 对象字段?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39916520/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mapping a dynamic json object field in Hymanson?
提问by Click Upvote
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. It isn't possible to map it to all possible values.
的payload
对象是不同的API服务,以及不同的API服务的不同方法获得的原始输出。不可能将其映射到所有可能的值。
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
为其适当的预期类?
回答by cassiomolin
Using JsonNode
使用 JsonNode
You could use JsonNode
from the com.fasterxml.Hymanson.databind
package:
您可以JsonNode
从com.fasterxml.Hymanson.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);
Mapping 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);
Considering a Map<String, Object>
考虑一个 Map<String, Object>
Depending on your requirements, you could use a Map<String, Object>
instead of JsonNode
:
根据您的要求,您可以使用 aMap<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:
如果您需要将 a 转换Map<String, Object>
为 POJO,请使用:
Payload payload = mapper.convertValue(event.getPayload(), Payload.class);
According to the Hymanson 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. However, same converters (serializers and deserializers) will be used as for data binding, meaning same object mapper configuration works.
根据 Hymanson文档,该convertValue()
方法在功能上类似于首先将给定值序列化为 JSON,然后将 JSON 数据绑定到给定类型的值,但应该更有效,因为完全序列化不会(需要)发生。但是,将使用相同的转换器(串行器和解串器)作为数据绑定,这意味着相同的对象映射器配置工作。
回答by Hector
Does this help?
这有帮助吗?
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.Hymanson.annotation.JsonAnyGetter;
import com.fasterxml.Hymanson.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.Hymanson.annotation.JsonCreator;
import com.fasterxml.Hymanson.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}]]