我在JSON
以下
{
"date":{
"year":2017,
"month":3,
"day":12
},
"name":"Jon",
"message":{
"product":"orange",
"price":2000
}
}
有时有时会如下JSON
所示:
{
"date":2017312,
"name":"Jon",
"message":{
"product":"orange",
"price":2000
}
}
请注意,日期可以是JSON object
或long
的值。如何将其解析为POJO
?我正在使用Jackson
库。
答案 0 :(得分:1)
执行此操作的一种方法是使用自定义解串器,您可以在其中逻辑检查字段。(例如https://dzone.com/articles/custom-json-deserialization-with-jackson)
字段长度可以是此处用来将其解析为元素的逻辑。
答案 1 :(得分:1)
您需要实现自定义反序列化程序,并使用JsonDeserialize
注释对给定的字段进行注释。对于以下POJO
模型:
class Pojo {
@JsonDeserialize(using = LocalDateJsonDeserializer.class)
private LocalDate date;
private String name;
private Message message;
// getters, setters
}
class Message {
private String product;
private int price;
// getters, setters
}
简单的反序列化器实现如下所示:
class LocalDateJsonDeserializer extends JsonDeserializer<LocalDate> {
@Override
public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
if (p.currentToken() == JsonToken.START_OBJECT) {
MapType mapType = ctxt.getTypeFactory().constructMapType(Map.class, String.class, Integer.class);
JsonDeserializer<Object> mapDeserializer = ctxt.findRootValueDeserializer(mapType);
Map<String, Integer> date = (Map<String, Integer>) mapDeserializer.deserialize(p, ctxt);
return LocalDate.of(date.get("year"), date.get("month"), date.get("day"));
} else if (p.currentToken() == JsonToken.VALUE_NUMBER_INT) {
// You need to be really careful here. Date format is ambiguous
// You should test it for all months and days
String date = p.getValueAsString();
int year = Integer.parseInt(date.substring(0, 4));
// much better to use always two digits for month: `03` instead `3`
int month = Integer.parseInt(date.substring(4, 5));
int day = Integer.parseInt(date.substring(5, 7));
return LocalDate.of(year, month, day);
} else if (p.currentToken() == JsonToken.VALUE_NULL) {
return null;
}
return null;
}
}
简单用法:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.io.IOException;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) throws Exception {
String json1 = "json 1 ...";
String json2 = "json 2....";
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.readValue(json1, Pojo.class));
System.out.println(mapper.readValue(json2, Pojo.class));
}
}
打印:
Pojo{date=2017-03-12, name='Jon', message=Message{product='orange', price=2000}}
Pojo{date=2017-03-12, name='Jon', message=Message{product='orange', price=2000}}
当然,您需要处理所有极端情况并改进错误处理,但是通常这就是我们应该如何处理可能具有以下不同格式的值的方法:JSON object
,JSON array
,primitives
。
对于LocalDateTime
,它的外观应类似。我们需要创建POJO
模型:
class Pojo {
@JsonDeserialize(using = LocalDateTimeJsonDeserializer.class)
private LocalDateTime time;
private String name;
private Message message;
// getters, setters, toString
}
自定义反序列化器可能如下所示:
class LocalDateTimeJsonDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
if (p.currentToken() == JsonToken.START_OBJECT) {
MapType mapType = ctxt.getTypeFactory().constructMapType(Map.class, String.class, Object.class);
JsonDeserializer<Object> mapDeserializer = ctxt.findRootValueDeserializer(mapType);
Map<String, Object> node = (Map<String, Object>) mapDeserializer.deserialize(p, ctxt);
Map<String, Integer> date = (Map<String, Integer>) node.get("date");
Map<String, Integer> time = (Map<String, Integer>) node.get("time");
LocalDate localDate = LocalDate.of(date.get("year"), date.get("month"), date.get("day"));
LocalTime localTime = LocalTime.of(time.get("hour"), time.get("minute"), time.get("second"), time.get("nano"));
return LocalDateTime.of(localDate, localTime);
} else if (p.currentToken() == JsonToken.VALUE_NUMBER_INT) {
// You need to be really careful here. Date format is ambiguous
// You should test it for all months and days
String date = p.getValueAsString();
// parse date string
// ...
return LocalDateTime.now();
} else if (p.currentToken() == JsonToken.VALUE_NULL) {
return null;
}
return null;
}
}
反序列化示例与LocalDate
相同。对于JSON
以下的有效负载:
{
"time": {
"date": {
"year": 2019,
"month": 3,
"day": 29
},
"time": {
"hour": 13,
"minute": 21,
"second": 20,
"nano": 620000000
}
},
"name": "Jon",
"message": {
"product": "orange",
"price": 2000
}
}
它应该打印:
Pojo{time=2019-03-29T13:21:20.620, name='Jon', message=Message{product='orange', price=2000}}
另外,看看涵盖所有java.time.*
类的JavaTimeModule
模块,并允许以标准方式进行序列化和反序列化,