Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing custom object that contains JodaTime objects into JSON

After running a second activity that creates an object and stores it into an ArrayList inside of a Singleton I get this error when returning to the first Activity from the creation Activity.

Logcat:

10-09 15:00:48.125: E/AndroidRuntime(4266): FATAL EXCEPTION: main
10-09 15:00:48.125: E/AndroidRuntime(4266): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nanospark.cnc/com.nanospark.cnc.ContactCreateActivity}: java.lang.RuntimeException: Failed to invoke public org.joda.time.Chronology() with no args
10-09 15:00:48.125: E/AndroidRuntime(4266):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at android.app.ActivityThread.access$600(ActivityThread.java:141)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at android.os.Handler.dispatchMessage(Handler.java:99)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at android.os.Looper.loop(Looper.java:137)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at android.app.ActivityThread.main(ActivityThread.java:5103)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at java.lang.reflect.Method.invokeNative(Native Method)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at java.lang.reflect.Method.invoke(Method.java:525)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at dalvik.system.NativeStart.main(Native Method)
10-09 15:00:48.125: E/AndroidRuntime(4266): Caused by: java.lang.RuntimeException: Failed to invoke public org.joda.time.Chronology() with no args
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:107)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:173)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:95)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:183)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:95)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:183)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.google.gson.Gson.fromJson(Gson.java:805)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.google.gson.Gson.fromJson(Gson.java:770)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.google.gson.Gson.fromJson(Gson.java:719)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.nanospark.cnc.GlobalData.retrieveGlobalDataFromStorage(GlobalData.java:92)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.nanospark.cnc.ContactCreateActivity.onCreate(ContactCreateActivity.java:38)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at android.app.Activity.performCreate(Activity.java:5133)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
10-09 15:00:48.125: E/AndroidRuntime(4266):     ... 11 more
10-09 15:00:48.125: E/AndroidRuntime(4266): Caused by: java.lang.InstantiationException: can't instantiate class org.joda.time.Chronology
10-09 15:00:48.125: E/AndroidRuntime(4266):     at java.lang.reflect.Constructor.constructNative(Native Method)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
10-09 15:00:48.125: E/AndroidRuntime(4266):     at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:104)
10-09 15:00:48.125: E/AndroidRuntime(4266):     ... 27 more

Singleton Code doing the JSON writing:

public void storeGlobalData(Context context){
    mPrefs = context.getSharedPreferences("com.nanospark.cnc", Context.MODE_PRIVATE);
    preferenceEditor = mPrefs.edit();
    Gson gson = new Gson();
    //Transform the ArrayLists into JSON Data.
    String machineProfileListJSON = gson.toJson(getMachineProfileList());
    String contactInfoListJSON = gson.toJson(getContactInfoList());
    String eventInfoListJSON = gson.toJson(getEventInfoList());
    preferenceEditor.putString("machineProfileListJSONData", machineProfileListJSON);
    preferenceEditor.putString("contactInfoListJSONData", contactInfoListJSON);
    preferenceEditor.putString("eventInfoListJSONData", eventInfoListJSON);
    //Commit the changes.
    preferenceEditor.commit();

}
public void retrieveGlobalDataFromStorage(Context context){
    mPrefs = context.getSharedPreferences("com.nanospark.cnc", Context.MODE_PRIVATE);
    if(mPrefs.contains("machineProfileListJSONData")){

        Gson gson = new Gson();
        String machineProfileListJSON = mPrefs.getString("machineProfileListJSONData", "");
        String contactInfoListJSON = mPrefs.getString("contactInfoListJSONData", "");
        String eventInfoListJSON = mPrefs.getString("eventInfoListJSONData", "");
          Type  machineProfileListType = new TypeToken<ArrayList<MachineProfile>>() {}.getType();
            machineProfileList = (gson.fromJson(machineProfileListJSON, machineProfileListType));

            Type contactInfoListType = new TypeToken<ArrayList<ContactInfo>>() {}.getType();
          contactInfoList = gson.fromJson(contactInfoListJSON, contactInfoListType );

          Type eventListType = new TypeToken<ArrayList<Event>>() {}.getType();
          eventInfoList = gson.fromJson(eventInfoListJSON, eventListType);
    }
}

Report Event Class that is trying to be written:

    package com.nanospark.cnc;

import java.util.ArrayList;

import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
public class ReportEvent extends Event {

    public ReportEvent(String eventTitle,String eventDescription,int assignedPin, String trackingType,
            LocalDate startDate, LocalDate endDate, boolean watchAllDay,
            LocalTime startTime, LocalTime endTime, ArrayList<String> selectedDays,
            ArrayList<ContactInfo> selectedContact, String formatChoice,
            ReportTimeSpec reportTimingConfig) {
        super(eventTitle,eventDescription, assignedPin, trackingType, startDate, endDate, watchAllDay,
                startTime, endTime, selectedDays, selectedContact, formatChoice,
                reportTimingConfig);
        // TODO Auto-generated constructor stub
    }

}

Generic Event Class that Report Event extends:

 package com.nanospark.cnc;

import java.util.ArrayList;
import java.util.Calendar;

import org.joda.time.LocalDate;
import org.joda.time.LocalTime;


public class Event {
    String eventTitle;
    String eventDescription;
    int assignedPin;
    String trackingType;
    LocalDate startDate;
    LocalDate endDate;
    boolean watchAllDay;
    LocalTime startTime;
    LocalTime endTime;
    ArrayList<String> selectedDays = new ArrayList<String>();
    ArrayList<ContactInfo> selectedContact = new ArrayList<ContactInfo>();
    String formatChoice;
    ReportTimeSpec reportTimingConfigs;

    public Event(){

    }
    public Event(String eventTitle, String eventDescription, int assignedPin, String trackingType,
            LocalDate startDate, LocalDate endDate, boolean watchAllDay,
            LocalTime startTime, LocalTime endTime, ArrayList<String> selectedDays,
            ArrayList<ContactInfo> selectedContact, String formatChoice, ReportTimeSpec reportTimingConfigs) {
        this.eventTitle = eventTitle;
        this.eventDescription = eventDescription;
        this.assignedPin = assignedPin;
        this.trackingType = trackingType;
        this.startDate = startDate;
        this.endDate = endDate;
        this.watchAllDay = watchAllDay;
        this.startTime = startTime;
        this.endTime = endTime;
        this.selectedDays = selectedDays;
        this.selectedContact = selectedContact;
        this.formatChoice = formatChoice;
        this.reportTimingConfigs = reportTimingConfigs;
    }



    public String getEventTitle() {
        return eventTitle;
    }

    public void setEventTitle(String eventTitle) {
        this.eventTitle = eventTitle;
    }

    public String getEventDescription() {
        return eventDescription;
    }

    public void setEventDescription(String eventDescription) {
        this.eventDescription = eventDescription;
    }

    public ReportTimeSpec getReportTimingConfigs() {
        return reportTimingConfigs;
    }

    public void setReportTimingConfigs(ReportTimeSpec reportTimingConfigs) {
        this.reportTimingConfigs = reportTimingConfigs;
    }

    public int getAssignedPin() {
        return assignedPin;
    }

    public void setAssignedPin(int assignedPin) {
        this.assignedPin = assignedPin;
    }

    public String getTrackingType() {
        return trackingType;
    }

    public void setTrackingType(String trackingType) {
        this.trackingType = trackingType;
    }

    public LocalDate getStartDate() {
        return startDate;
    }

    public void setStartDate(LocalDate startDate) {
        this.startDate = startDate;
    }

    public LocalDate getEndDate() {
        return endDate;
    }

    public void setEndDate(LocalDate endDate) {
        this.endDate = endDate;
    }

    public boolean isWatchAllDay() {
        return watchAllDay;
    }

    public void setWatchAllDay(boolean watchAllDay) {
        this.watchAllDay = watchAllDay;
    }

    public LocalTime getStartTime() {
        return startTime;
    }

    public void setStartTime(LocalTime startTime) {
        this.startTime = startTime;
    }

    public LocalTime getEndTime() {
        return endTime;
    }

    public void setEndTime(LocalTime endTime) {
        this.endTime = endTime;
    }

    public ArrayList<String> getSelectedDays() {
        return selectedDays;
    }

    public void setSelectedDays(ArrayList<String> selectedDays) {
        this.selectedDays = selectedDays;
    }

    public ArrayList<ContactInfo> getSelectedContact() {
        return selectedContact;
    }

    public void setSelectedContact(ArrayList<ContactInfo> selectedContact) {
        this.selectedContact = selectedContact;
    }

    public String getFormatChoice() {
        return formatChoice;
    }

    public void setFormatChoice(String formatChoice) {
        this.formatChoice = formatChoice;
    }

    public ReportTimeSpec getReportTimeSpec() {
        return reportTimingConfigs;
    }

    public void setReportTimeSpec(ReportTimeSpec reportTimingConfigs) {
        this.reportTimingConfigs = reportTimingConfigs;
    }
    @Override
    public String toString(){
        return this.eventTitle;
    }

}
like image 452
Timothy Frisch Avatar asked Oct 09 '14 20:10

Timothy Frisch


1 Answers

Converters from https://github.com/gkopff/gson-javatime-serialisers are for java.time classes from Java8, e.g. java.time.LocalDate.

But you need converters for org.joda.time classes from 3rd part library. You can create custom converters for it, like:

Converter for org.joda.time.LocalDate

public class LocalDateSerializer implements JsonDeserializer<LocalDate>, JsonSerializer<LocalDate>
{
   private static final DateTimeFormatter DATE_FORMAT = ISODateTimeFormat.date();

   @Override
   public LocalDate deserialize(final JsonElement je, final Type type,
                           final JsonDeserializationContext jdc) throws JsonParseException
   {
      final String dateAsString = je.getAsString();
      if (dateAsString.length() == 0)
      {
         return null;
      }
      else
      {
         return DATE_FORMAT.parseLocalDate(dateAsString);         
      }
   }

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

Converter for org.joda.time.LocalTime

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.getAsString();
      if (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);
   }

}  

Usage

public void retrieveGlobalDataFromStorage(Context context)
{  
// ...  

    final GsonBuilder builder = new GsonBuilder()
       .registerTypeAdapter(LocalDate.class, new LocalDateSerializer())
       .registerTypeAdapter(LocalTime.class, new LocalTimeSerializer());
    final Gson gson = builder.create();  
// ...
like image 71
Ilya Avatar answered Oct 27 '22 12:10

Ilya