JodaTime LocalDate / LocalTime不使用自定义JSON Serializer类进行解析

我有一个名为ReportEvent的对象,它接受来自JodaTime API /框架的JodaTimeLocalDate 。 此ReportEvent可以通过谷歌的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 Serializer / Deserializer。

 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, JsonSerializer { 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 Serializer / Deserializer。

 public class LocalDateSerializer implements JsonSerializer, JsonDeserializer { 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初始化)提取到一个单独的方法,您可以从您的方法调用。

使用deserialize()时要小心谨慎

  return fmt.parseLocalDate(json.toString()); 

因为它产生了可能出乎意料的引号""2014-10-28""

使用它可能更好:

  return fmt.parseLocalDate(json.getAsString());