JodaTime LocalDate / LocalTime does not parse custom JSON Serializer classes

I have an object called ReportEvent that accepts LocalTime as well as LocalDate from the JodaTime API / framework. This ReportEvent can be written to JSON using the google GSON conversion API. However, JodaTime partial deserialization causes problems.

Logcat error report:

 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 

Relevant sections of code:

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<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 serializer / deserializer.

 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()); } } 
+2
source share
2 answers

The problem is the code that you have that serializes the data.

In the original question, you have this code when you are going to deserialize ( retrieveGlobalDataFromStorage ):

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

But when you are going to serialize ( storeGlobalData ), you just have:

 Gson gson = new Gson(); 

You must register type adapters in both places. I will extract this code ( Gson initialization) into a separate method that you can call from both methods.

+2
source

It is also worth being careful in deserialize() with

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

as it creates likely unexpected quotation marks ""2014-10-28"" .

Better to use instead:

  return fmt.parseLocalDate(json.getAsString()); 
+2
source

Source: https://habr.com/ru/post/1204362/


All Articles