3

I need to create a custom deserializer so I can correctly deserialize a date that I'm receiving in this format: 2011-10-19T23:30:00-04:00. My Date object is one of many fields, contained one of many nested classes of the Object that I'm deserializing. Everything works fine except for the Date. My class looks like this:

public class OfferContainer{

    public Offer offer;

    public OfferContainer(){}   

    @Override
    public String toString()
    {
        return this.getID() +  offer.toString();
    }

    public String getDescription() {
        return offer.description;
    }

    public String getBusinessName() {
        return offer.business.name;
    }



    public class Offer
    {
        public Category category;
        public String description;
        public String discount;
        public Date expiration;
        public Date published;
        public String rescinded_at;
        public String title;
        public String hook;
        public Date valid_from;
        public Date valid_to;
        public String id;
        public Business business;
        public Location location;
        public String image_270x155;


        @Override
        public String toString()
        {
            return String.format(
                    "[Offer: category=%1$s, description=%2$s, discount=%3$s, expiration=%4$s, published=%5$s, rescinded_at=%6$s, title=%7$s, valid_from=%8$s, valid_to=%9$s, id=%10$s, business=%11$s, location=%12$s]",
                    category, description, discount, expiration, published, rescinded_at, title, valid_from, valid_to, id,
                    business, location);
        }

    }

   public enum Category
    {
        Salon, Spa, Restaurant, Other
    }



    public class Business
    {
        public String name;
        public String phone;
        public Address address;


        @Override
        public String toString()
        {
            return String.format(
                    "[Business: name=%1$s, phone=%2$s, address=%3$s]",
                    name, phone, address);
        }
    }


    public  class Address
    {
        public String address_1;
        public String address_2;
        public String city;
        public String cross_streets;
        public String state;
        public String zip;



        @Override
        public String toString()
        {
            return String.format(
                    "[Address: address_1=%1$s, address_2=%2$s, city=%3$s, cross_streets=%4$s, state=%5$s, zip=%6$s]",
                    address_1, address_2, city, cross_streets, state, zip);
        }
    }

    public class Location {
        public double latitude;
        public double longitude;



        public String toString() {
            return String.format("[Location: longitude=%1$s, latitude=%2$s]", longitude, latitude);
        }

    }

}

How do I use registerTypeAdapter in this scenario and how do I correctly implement a custom deserializer for this?

Thanks in advance!

Also, if it matters, here's how I'm actually getting my POJO:

  OfferContainer[] offers = gson.fromJson(json, OfferContainer[].class);

Here's the JSON:

{
    "offer":{
        "category":"Salon",
        "description":"Use this offer now to enjoy this great Salon at a 20% discount. ",
        "discount":"20",
        "expiration":"2011-04-08T02:30:00Z",
        "published":"2011-04-07T12:00:33Z",
        "rescinded_at":null,
        "title":"20% off at Jun Hair Salon",
        "valid_from":"2011-04-07T12:00:31Z",
        "valid_to":"2011-04-08T02:00:00Z",
        "id":"JUN_HAIR_1302177631",
        "business":{
            "name":"Jun Hair Salon",
            "phone":"2126192989",
            "address":{
                "address_1":"12 Mott St",
                "address_2":null,
                "city":"New York",
                "cross_streets":"Chatham Sq & Worth St",
                "state":"NY",
                "zip":"10013"
            }
        },
        "location":{
            "latitude":"40.714021",
            "longitude":"-73.998663"
        },
        "distance":619.8162766744034,
        "draws":[
            "Hair Cut",
            "Blow Dry",
            "Blow Dry Treatment"
        ],
        "claim_link":"http://m-s.com/offers/JUN_HAIR_1302177631?app_id=SavIMg",
        "mobile_claim_link":"http://m-s.com/offers/JUN_HAIR_1302177631?app_id=SavIMg"
    }
}
LuxuryMode
  • 33,401
  • 34
  • 117
  • 188

1 Answers1

3

You need to implement JSONDeserializer<OfferContainer> and then override the deserialize method to achieve this. Have a look at this SO question GSON deserializing key-value to custom object

You can also try setting the dateformat in the GsonBuilder like this

 Gson gson = new GsonBuilder()
     .setDateFormat("yyyy-MM-dd'T'HHmmss.SSS'Z'")
     .create();
 OfferContainer [] offers = gson.fromJson(json, OfferContainer[].class);
Community
  • 1
  • 1
Narendra Yadala
  • 9,554
  • 1
  • 28
  • 43
  • But I can provide the deserialization implementation only for the Date object and the rest will work as before? (BTW, I've already seen the answer you referenced and was still confused about the above...) Thanks @Narendra! – LuxuryMode Oct 25 '11 at 20:47
  • @LuxuryMode I suggest writing a custom deserializer for the most atomic class which is not working using the regular gson deserialization process. In your case it is `Offer.java`. AFAIK, You cannot custom deserialize a specific part of your Offer class. I can try to write a deserializer for `Offer.java` if you can provide me with the JSON for your object. – Narendra Yadala Oct 26 '11 at 07:08
  • @LuxuryMode Did you try `new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")`? I think this should work for you, but make sure to replace the `:` in the timezone with empty string. And it should work for you without any custom deserialization. Can you try it and let me know if that is good for you. – Narendra Yadala Oct 26 '11 at 14:28
  • @LuxuryMode If you are having `Z` literal and not actual timezone, then you can use `new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HHmmss.SSS'Z'")` – Narendra Yadala Oct 26 '11 at 14:46
  • Thanks @Narendra! Can you show me the full syntax that would work with `OfferContainer[] offers = gson.fromJson(json, OfferContainer[].class);` as I posted above? – LuxuryMode Oct 26 '11 at 15:04
  • thanks so much for help and patience. Seems to work just fine so far, though its hard to know for sure because I was only having problems with the default serialization for certain dates/times (like 2011-10-19T23:30:00-04:00). I'll continue to test and make sure it works. Thanks again. – LuxuryMode Oct 26 '11 at 15:34
  • getting a syntaxexception again with this date from json: `"2011-10-26T20:29:59-07:00"` :( – LuxuryMode Oct 27 '11 at 01:11
  • @LuxuryMode if you have real timezone then you cannot use `new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")`..the json you gave in your question has `Z` literal in the json. In your comment, you seem to have a real timezone `-07:00`, even this is not a proper format. It has to be either `-0700` or `GMT-07:00` (see here http://download.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html ) Looks like Jave 7 has a new date format for `-07:00` which goes like this `"yyyy-MM-dd'T'HH:mm:ssX"` – Narendra Yadala Oct 27 '11 at 02:35