Отображение динамического поля объекта json в Джексоне?
у меня есть объекты json в следующей схеме:
{
name: "foo",
timestamp: 1475840608763,
payload:
{
foo: "bar"
}
}
здесь payload
поле содержит внедренный объект json, и схема этого объекта является динамической и отличается каждый раз.
на payload
object-это исходные данные, полученные из разных служб API, и различные методы различных служб API. Невозможно сопоставить его со всеми возможными значениями.
возможно ли иметь класс java, такой как следующий:
public class Event
{
public String name;
public long timestamp;
public JsonObject payload;
}
или что-то в этом роде, поэтому я могу получить основную схему и обработать ее, а затем отправить ее в соответствующий класс, который преобразует payload
к соответствующему ожидаемому классу?
2 ответов
используя JsonNode
можно использовать JsonNode
С 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<String, Object>
в зависимости от ваших требований, вы можете использовать Map<String, Object>
вместо JsonNode
:
public class Event {
public String name;
public long timestamp;
public Map<String, Object> payload;
// Getters and setters
}
Если вам нужно преобразовать Map<String, Object>
в POJO, используйте:
Payload payload = mapper.convertValue(event.getPayload(), Payload.class);
согласно Джексону документация на convertValue()
метод функционально похож на первую сериализацию заданного значения в 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<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 + "]";
}
}
тогда это класс владения
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}]]