【问题标题】:Java 8 LocalDateTime deserialized using GsonJava 8 LocalDateTime 使用 Gson 反序列化
【发布时间】:2023-04-04 13:50:02
【问题描述】:

我有一个日期时间属性格式为“2014-03-10T18:46:40.000Z”的 JSON,我想使用 Gson 将其反序列化为 java.time.LocalDateTime 字段。

当我尝试反序列化时,我得到了错误:

java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING

【问题讨论】:

  • 这是在序列化或反序列化期间发生的。如果是第二个 - 检查您的 json 是否有效 - 例如它必须以 { (又名 BEGIN_OBJECT)开头,但您的 json 以字符开头
  • 我在反序列化过程中犯了一个错误。 json -> 对象。但我认为我的 Json 还可以。如果我在我的对象中将我的属性 LocalDateTime 替换为 String 它可以工作。
  • json 格式为{"key":"value"} 你的json 肯定是无效的。正如我在 gson 中所说的 {BEGIN_OBJECT 并且它说它丢失了。只需println() json 即可检查它是否正确。您也可以打印serialized 对象以查看 json 的外观:)
  • 好的,我现在明白为什么它不起作用了。但也许你知道我能做些什么吗?就像 Gson 的特殊选项一样,如果我有一个带有特殊日期和时间的字符串来反序列化这个字段并创建我需要的对象?
  • 在看到字符串之前,我无法告诉您任何事情。但无论哪种方式,除非它是有效的 json,否则您无法对其进行反序列化。恕我直言,你能做的最好的(也许是唯一的)事情就是让这个字符串成为有效的 json。

标签: java json java-8 gson


【解决方案1】:

当您反序列化 LocalDateTime 属性时会发生错误,因为 GSON 无法解析该属性的值,因为它不知道 LocalDateTime 对象。

使用 GsonBuilder 的 registerTypeAdapter 方法来定义自定义的 LocalDateTime 适配器。 以下代码 sn -p 将帮助您反序列化 LocalDateTime 属性。

Gson gson = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() {
    @Override
    public LocalDateTime deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
        Instant instant = Instant.ofEpochMilli(json.getAsJsonPrimitive().getAsLong());
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }
}).create();

【讨论】:

    【解决方案2】:

    要扩展@Randula 的答案,将分区日期时间字符串 (2014-03-10T18:46:40.000Z) 解析为 JSON:

    Gson gson = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() {
    @Override
    public LocalDateTime deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
        return ZonedDateTime.parse(json.getAsJsonPrimitive().getAsString()).toLocalDateTime();
    }
    }).create();
    

    【讨论】:

    【解决方案3】:

    进一步扩展@Evers 答案:

    您可以像这样使用 lambda 进一步简化:

    GSON GSON = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, (JsonDeserializer<LocalDateTime>) (json, type, jsonDeserializationContext) ->
        ZonedDateTime.parse(json.getAsJsonPrimitive().getAsString()).toLocalDateTime()).create();
    

    【讨论】:

      【解决方案4】:

      以下对我有用。

      Java:

      Gson gson = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() { 
      @Override 
      public LocalDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
      
      return LocalDateTime.parse(json.getAsString(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); } 
      
      }).create();
      
      Test test = gson.fromJson(stringJson, Test.class);
      

      其中 stringJson 是存储为 String 类型的 Json

      Json:

      "dateField":"2020-01-30 15:00"

      其中 dateField 属于 LocalDateTime 类型,存在于 stringJson 字符串变量中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-03-12
        • 1970-01-01
        • 1970-01-01
        • 2019-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        相关资源
        最近更新 更多