我要放弃了。我已经浏览了所有可能的 SO 页面,但我无法让它工作。
我有一个ConfigKeyVal这样的课程:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class ConfigKeyValue {
private String name;
private NssConfigDto value;
}
Run Code Online (Sandbox Code Playgroud)
凡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;
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试将ConfigKeyVal(顶部的)对象的JSON 数组直接反序列化到我的 ArrayList 中。
public class ConfigKeyValueList extends ArrayList<ConfigKeyValue> {
public ConfigKeyValueList() {
super();
}
}
Run Code Online (Sandbox Code Playgroud)
像这样:
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();
}
Run Code Online (Sandbox Code Playgroud)
我试过使用,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'
Run Code Online (Sandbox Code Playgroud)
编辑:这就是 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"
}
}
}
}
]
Run Code Online (Sandbox Code Playgroud)
首先,我不建议像这样序列化日期。我强烈建议您遵守标准并使用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());
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以LocalDateTime在你的 bean 中使用你的,让 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);
Run Code Online (Sandbox Code Playgroud)
如果您无法控制 JSON,那么您将需要一个自定义的 deserializer。实现可以是这样的:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后注释您的字段以使用上面定义的反序列化器:
@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;
}
Run Code Online (Sandbox Code Playgroud)
最后解析你的 JSON 文档:
ObjectMapper mapper = new ObjectMapper();
TypeReference<List<ConfigKeyValue>> typeRef = new TypeReference<>() {};
List<ConfigKeyValue> list = mapper.readValue(json, typeRef);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3308 次 |
| 最近记录: |