我放弃了。我浏览了所有可能的SO页面,但无法正常工作。
我有一个这样的课程ConfigKeyVal
:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class ConfigKeyValue {
private String name;
private NssConfigDto value;
}
Config
类的位置如下:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Config {
private String name;
private String source;
private String destination;
private int cycle;
private LocalDateTime fixedTime;
private LocalDateTime submitDate;
}
我正在尝试将ConfigKeyVal
(上一个)对象的JSON数组直接反序列化到我的ArrayList中。
public class ConfigKeyValueList extends ArrayList<ConfigKeyValue> {
public ConfigKeyValueList() {
super();
}
}
赞:
final Data values = result.results().get("attributes"); // this is an array of ConfigKeyValue objects
ObjectMapper mapper = new ObjectMapper();
ConfigKeyValueList configKeyValueList = new ConfigKeyValueList();
try {
configKeyValueList = mapper.readValue(values.asText(), ConfigKeyValueList.class);
} catch (IOException e) {
e.printStackTrace();
}
我尝试使用mapper.registerModule(new JavaTimeModule());
,但这没有帮助。我是否必须为此编写自己的解串器,或者是否有有效的工具,但我做错了?
我遇到的错误是:com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.time.LocalDateTime: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?))
我在gradle文件中使用了那些jackson依赖项:
compile group: 'com.fasterxml.jackson.module', name: 'jackson-module-parameter-names', version: '2.9.6'
compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jdk8', version: '2.9.6'
compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.9.6'
编辑:这就是JSON的样子
[
{
"name": "kek1",
"value": {
"name": "kek1",
"source": "source",
"destination": "dest",
"cycle": 1,
"fixedTime": {
"year": 2017,
"month": "APRIL",
"dayOfYear": 95,
"dayOfWeek": "WEDNESDAY",
"dayOfMonth": 5,
"monthValue": 4,
"hour": 4,
"minute": 20,
"second": 0,
"nano": 0,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
}
},
"submitDate": {
"year": 2017,
"month": "APRIL",
"dayOfYear": 95,
"dayOfWeek": "WEDNESDAY",
"dayOfMonth": 5,
"monthValue": 4,
"hour": 4,
"minute": 20,
"second": 0,
"nano": 0,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
}
}
}
},
{
"name": "kek2",
"value": {
"name": "kek2",
"source": "source",
"destination": "dest",
"cycle": 1,
"fixedTime": {
"year": 2017,
"month": "APRIL",
"dayOfYear": 93,
"dayOfWeek": "MONDAY",
"dayOfMonth": 3,
"monthValue": 4,
"hour": 5,
"minute": 10,
"second": 0,
"nano": 0,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
}
},
"submitDate": {
"year": 2017,
"month": "APRIL",
"dayOfYear": 93,
"dayOfWeek": "MONDAY",
"dayOfMonth": 3,
"monthValue": 4,
"hour": 5,
"minute": 10,
"second": 0,
"nano": 0,
"chronology": {
"id": "ISO",
"calendarType": "iso8601"
}
}
}
}
]
答案 0 :(得分:1)
首先,我不建议像这样序列化日期。我强烈建议您遵循标准并使用ISO 8601和RFC 3339认可的xkcd 1179:
如果您使用Spring Data MongoDB,则可以使用MongoCustomConversions
为您处理从Date
和LocalDateTime
进行的转换:
@Configuration
public class MongoConfiguration {
@Bean
public MongoCustomConversions customConversions() {
List<Converter<?, ?>> converters = new ArrayList<>();
converters.add(new DateToLocalDateTimeConverter());
converters.add(new LocalDateTimeToDateConverter());
return new MongoCustomConversions(converters);
}
class DateToLocalDateTimeConverter implements Converter<Date, LocalDateTime> {
@Override
public LocalDateTime convert(Date source) {
return source == null ? null :
LocalDateTime.ofInstant(source.toInstant(), ZoneId.systemDefault());
}
}
class LocalDateTimeToDateConverter implements Converter<LocalDateTime, Date> {
@Override
public Date convert(LocalDateTime source) {
return source == null ? null : Date.from(source.toInstant());
}
}
}
然后,您可以在豆中使用LocalDateTime
,然后让Jackson和JavaTimeModule
处理序列化/反序列化:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// Serialize
List<ConfigKeyValue> list = null;
String json = mapper.writeValueAsString(list);
// Deserialize
TypeReference<List<ConfigKeyValue>> typeRef = new TypeReference<>() {};
list = mapper.readValue(json, typeRef);
如果您无法控制JSON,则需要自定义反序列化器。实现可以像:
public class CustomLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException {
JsonNode tree = jp.getCodec().readTree(jp);
int year = tree.get("year").asInt();
int month = tree.get("monthValue").asInt();
int dayOfMonth = tree.get("dayOfMonth").asInt();
int hour = tree.get("hour").asInt();
int minute = tree.get("minute").asInt();
int second = tree.get("second").asInt();
int nano = tree.get("nano").asInt();
return LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nano);
}
}
然后注释您的字段以使用上面定义的反序列化器:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Config {
// Other fields
@JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)
private LocalDateTime fixedTime;
@JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)
private LocalDateTime submitDate;
}
最后解析您的JSON文档:
ObjectMapper mapper = new ObjectMapper();
TypeReference<List<ConfigKeyValue>> typeRef = new TypeReference<>() {};
List<ConfigKeyValue> list = mapper.readValue(json, typeRef);
答案 1 :(得分:0)
您必须将模块添加到ObjectMapper
private ObjectMapper getMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.INDENT_OUTPUT,false);
mapper.setSerializationInclusion(Include.NON_NULL);
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
return mapper;
}
由于杰克逊的最新版本是JavaTimeModule,所以以前是JSR310Module
编辑: 应该同时用于序列化/反序列化,您可能会误会是mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
JSON格式应为ISO:
{
"name": "kek2",
"value": {
"name": "kek2",
"source": "source",
"destination": "dest",
"cycle": 1,
"fixedTime": "2018-07-17T15:10:55"
...
答案 2 :(得分:-1)
Jackson无法从任何JSON字符串值反序列化LocalDateTime对象。
将LocalDateTime对象更改为“字符串”。