java - JodaTime LocalDate/LocalTime 不使用自定义 JSON 序列化程序类进行解析

标签 java android json gson jodatime

我有一个名为 ReportEvent 的对象,它接受一个 LocalTime 以及一个来自 JodaTimeLocalDate API/框架。此 ReportEvent 可以通过 google 的 GSON 转换 API 写入 JSON。但是,当反序列化 JodaTime partial 时会导致问题。

Logcat 错误报告:

10-16 13:23:01.812: E/AndroidRuntime(8884): FATAL EXCEPTION: main
10-16 13:23:01.812: E/AndroidRuntime(8884): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nanospark.cnc/com.nanospark.cnc.MainActivity}: java.lang.IllegalArgumentException: Invalid format: "{"iChronology":{"iBase":{"iMinDa..."
10-16 13:23:01.812: E/AndroidRuntime(8884):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at android.app.ActivityThread.access$600(ActivityThread.java:141)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at android.os.Handler.dispatchMessage(Handler.java:99)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at android.os.Looper.loop(Looper.java:137)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at android.app.ActivityThread.main(ActivityThread.java:5103)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at java.lang.reflect.Method.invokeNative(Native Method)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at java.lang.reflect.Method.invoke(Method.java:525)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at dalvik.system.NativeStart.main(Native Method)
10-16 13:23:01.812: E/AndroidRuntime(8884): Caused by: java.lang.IllegalArgumentException: Invalid format: "{"iChronology":{"iBase":{"iMinDa..."
10-16 13:23:01.812: E/AndroidRuntime(8884):     at org.joda.time.format.DateTimeFormatter.parseLocalDateTime(DateTimeFormatter.java:854)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at org.joda.time.format.DateTimeFormatter.parseLocalDate(DateTimeFormatter.java:798)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.nanospark.cnc.LocalDateSerializer.deserialize(LocalDateSerializer.java:32)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.nanospark.cnc.LocalDateSerializer.deserialize(LocalDateSerializer.java:1)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.google.gson.TreeTypeAdapter.read(TreeTypeAdapter.java:58)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:95)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:183)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.google.gson.Gson.fromJson(Gson.java:805)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.google.gson.Gson.fromJson(Gson.java:770)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.google.gson.Gson.fromJson(Gson.java:719)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.nanospark.cnc.GlobalData.retrieveGlobalDataFromStorage(GlobalData.java:118)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at com.nanospark.cnc.MainActivity.onCreate(MainActivity.java:35)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at android.app.Activity.performCreate(Activity.java:5133)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
10-16 13:23:01.812: E/AndroidRuntime(8884):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
10-16 13:23:01.812: E/AndroidRuntime(8884):     ... 11 more

相关代码段:

LocalTime 序列化器/反序列化器。

package com.nanospark.cnc;

import java.lang.reflect.Type;

import org.joda.time.LocalTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;


public class LocalTimeSerializer implements JsonDeserializer<LocalTime>, JsonSerializer<LocalTime>
{

   private static final DateTimeFormatter TIME_FORMAT = ISODateTimeFormat.timeNoMillis();

   @Override
   public LocalTime deserialize(final JsonElement je, final Type type,
                           final JsonDeserializationContext jdc) throws JsonParseException
   {
      final String dateAsString = je.toString();
      if (je.isJsonNull() || dateAsString.length() == 0)
      {
         return null;
      }
      else
      {
         return TIME_FORMAT.parseLocalTime(dateAsString);         
      }
   }

   @Override
   public JsonElement serialize(final LocalTime src, final Type typeOfSrc,
                                final JsonSerializationContext context)
   {
      String retVal;
      if (src == null)
      {
         retVal = "";
      }
      else
      {
         retVal = TIME_FORMAT.print(src);
      }
      return new JsonPrimitive(retVal);
   }

}

LocalDate 序列化器/反序列化器。

public class LocalDateSerializer implements JsonSerializer<LocalDate>, JsonDeserializer<LocalDate>
{

  private static final String PATTERN = "yyyy-MM-dd";
  final DateTimeFormatter fmt = DateTimeFormat.forPattern(PATTERN);


  @Override
  public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context)
  {
    String retVal = fmt.print(src);
    Log.v("MY LOCALDATE SERIALIZED", retVal);
    return new JsonPrimitive(retVal);
  }


  @Override
  public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException
  {

    Log.v("MY LOCALDATE DESERIALIZED",json.toString());
    return fmt.parseLocalDate(json.toString());
  }
}

最佳答案

问题出在序列化数据的代码上。

在您原来的问题中,当您要反序列化(retrieveGlobalDataFromStorage)时,您有这段代码:

final GsonBuilder builder = new GsonBuilder()
   .registerTypeAdapter(LocalDate.class, new LocalDateSerializer())
   .registerTypeAdapter(LocalTime.class, new LocalTimeSerializer());
final Gson gson = builder.create();  

但是当您要序列化 (storeGlobalData) 时,您只需:

Gson gson = new Gson();

您应该在两个 地方注册类型适配器。我将该代码(Gson 初始化)提取到一个单独的方法中,您可以从两个方法中调用该方法。

关于java - JodaTime LocalDate/LocalTime 不使用自定义 JSON 序列化程序类进行解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26411379/

相关文章:

java - 如何在java中读取文本文件到不同对象类型的ArrayList?

java - org.eclipse.persistence.moxy;2.3.2 : not found when resolving jersey-bundle 1. 19.1

java - 最佳实践 : instance variables filling over time

android - 使用抽屉导航和 fragment 未出现工具栏菜单

php - var_dump 变量在 php 中不返回任何内容

asp.net-mvc - 有没有办法让Ajax.BeginForm返回JSON并自动更新Form

JavaFX8 后台线程仍然干扰 GUI

java - 我的 UI 不会因数据更改而更新

ios - 如何从 iOS 中的字典中获取值

android - 什么是现有 SQLite 数据库的完整 Android 数据库助手类?