Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GSON deserializing key-value to custom object

I need to deserialize json which is an array of date/long values. Here is an example of the returned JSON:

[{"2011-04-30T00:00:00-07:00":100}, {"2011-04-29T00:00:00-07:00":200}]

Using GSON I am able to deserialize this to a List<Map<Date,String>>, but would like to be able to convert it to a List<MyCustomClass> similar to:

public class MyCustomClass() { 
    Date date;
    Long value;
}

I cannot seem to find a way to instruct GSON to map the key/value of the JSON map to the date/value fields in my custom class. Is there a way to do this, or is a list of maps the only route?

like image 425
Rich Kroll Avatar asked May 01 '11 01:05

Rich Kroll


1 Answers

You need to write a custom deserializer. You also need to use a time zone format that SimpleDateFormat can actually parse. Neither z nor Z will match -07:00, which is a weird mix of RFC 822 time zone format (-0700) or a "general time zone" (Mountain Standard Time or MST or GMT-07:00). Alternately, you can stick with the exact same time zone format, and use JodaTime's DateTimeFormat.

MyCustomClass.java

public class MyCustomClass
{
    Date date;
    Long value;

    public MyCustomClass (Date date, Long value)
    {
        this.date = date;
        this.value = value;
    }

    @Override
    public String toString()
    {
        return "{date: " + date + ", value: " + value + "}";
    }
}

MyCustomDeserializer.java

public class MyCustomDeserializer implements JsonDeserializer<MyCustomClass>
{
    private DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz");

    @Override
    public MyCustomClass deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) throws JsonParseException
    {
        JsonObject obj = json.getAsJsonObject();
        Entry<String, JsonElement> entry = obj.entrySet().iterator().next();
        if (entry == null) return null;
        Date date;
        try
        {
            date = df.parse(entry.getKey());
        }
        catch (ParseException e)
        {
            e.printStackTrace();
            date = null;
        }
        Long value = entry.getValue().getAsLong();
        return new MyCustomClass(date, value);
    }
}

GsonTest.java

public class GsonTest
{
    public static void main(String[] args)
    {
        // Note the time zone format tweak (removed the ':')
        String json = "[{\"2011-04-30T00:00:00-0700\":100}, {\"2011-04-29T00:00:00-0700\":200}]";

        Gson gson =
            new GsonBuilder()
            .registerTypeAdapter(MyCustomClass.class, new MyCustomDeserializer())
            .create();
        Type collectionType = new TypeToken<Collection<MyCustomClass>>(){}.getType();
        Collection<MyCustomClass> myCustomClasses = gson.fromJson(json, collectionType);
        System.out.println(myCustomClasses);
    }
}

All of the above code is on Github, feel free to clone (though you'll get code for answers to other questions as well).

like image 155
Matt Ball Avatar answered Sep 20 '22 12:09

Matt Ball