簡體   English   中英

使用LocalDateTime字段將JSON反序列化為對象

[英]Deserializing JSON to Object with LocalDateTime field

我放棄了 我已經瀏覽了所有可能的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"
                }
            }
        }
    }
]

首先,我不建議像這樣序列化日期。 我強烈建議您堅持使用標准,並使用RFC 3339xkcd 1179認可的ISO 8601

xkcd 1179: ISO 8601


如果您可以控制JSON序列化

如果使用Spring Data MongoDB ,則可以使用MongoCustomConversions為您處理從DateLocalDateTime進行的轉換:

@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());
        }
    }
}

然后,您可以在bean中使用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);

您必須將模塊添加到您的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"
...

Jackson沒有辦法從任何JSON字符串值反序列化LocalDateTime對象。

將LocalDateTime對象更改為“ String”。

將 json 反序列化為列表<object><div id="text_translate"><p>我有 json:</p><pre> "taxLevels": [{ "code": "VAT", "percentage": 19.0 } ]</pre><p> 這確實是List&lt;TTaxLevel&gt;</p><p> 我有<strong>Model.class</strong> :</p><pre> public class Model{ private final List&lt;TTaxLevel&gt; taxLevels; }</pre><p> 和<strong>TtaxLevel.class</strong> :</p><pre> @NoArgsConstructor public class TTaxLevel { private String code; private Double percentage; }</pre><p> 但我在這里收到錯誤:</p><blockquote><p> [Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of java.util.LinkedHashMap&lt;java.lang.String,java.lang.String&gt; out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of java.util.LinkedHashMap&lt;java.lang.String,java.lang.String&gt; out of START_ARRAY token at [Source: (PushbackInputStream); 行:36,列:19](通過參考鏈:...Model["taxLevels"])]]</p></blockquote><p> 我可以以某種方式強制jackson在這里ArrayList而不是Map嗎? 這是一個問題。</p><p> 這是反序列化代碼:</p><pre> Model model = new ObjectMapper().readValue(content, Model.class);</pre></div></object>

[英]Deserializing json as List<Object>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

相關問題 使用GSON將JSON對象反序列化為字符串字段 如何將java對象轉換為簡單的json字符串而不將LocalDateTime字段轉換為擴展的json對象? 使用Gson在java中將LocalDateTime序列化和反序列化為RFC 3339格式的JSON 反序列化JSON對象 將 json 反序列化為列表<object><div id="text_translate"><p>我有 json:</p><pre> "taxLevels": [{ "code": "VAT", "percentage": 19.0 } ]</pre><p> 這確實是List&lt;TTaxLevel&gt;</p><p> 我有<strong>Model.class</strong> :</p><pre> public class Model{ private final List&lt;TTaxLevel&gt; taxLevels; }</pre><p> 和<strong>TtaxLevel.class</strong> :</p><pre> @NoArgsConstructor public class TTaxLevel { private String code; private Double percentage; }</pre><p> 但我在這里收到錯誤:</p><blockquote><p> [Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of java.util.LinkedHashMap&lt;java.lang.String,java.lang.String&gt; out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of java.util.LinkedHashMap&lt;java.lang.String,java.lang.String&gt; out of START_ARRAY token at [Source: (PushbackInputStream); 行:36,列:19](通過參考鏈:...Model["taxLevels"])]]</p></blockquote><p> 我可以以某種方式強制jackson在這里ArrayList而不是Map嗎? 這是一個問題。</p><p> 這是反序列化代碼:</p><pre> Model model = new ObjectMapper().readValue(content, Model.class);</pre></div></object> 將 LocalDateTime Object 轉換為 LocalDateTime 基於對象類型反序列化JSON 使用列表屬性將JSON反序列化為Object 用傑克遜反序列化嵌套的json對象 將多態 Json object 反序列化為 POJO
 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM