web-dev-qa-db-ja.com

GSONがKey-Valueをカスタムオブジェクトに逆シリアル化する

日付/長さの値の配列であるjsonを逆シリアル化する必要があります。返されるJSONの例を次に示します。

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

GSONを使用して、これをList<Map<Date,String>>に逆シリアル化できますが、次のようなList<MyCustomClass>に変換できるようにしたいと思います。

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

JSONマップのキー/値をカスタムクラスの日付/値フィールドにマップするようにGSONに指示する方法が見つからないようです。これを行う方法はありますか、それともマップのリストが唯一のルートですか?

18
Rich Kroll

カスタムデシリアライザーを作成する必要があります。また、 SimpleDateFormat が実際に解析できるタイムゾーン形式を使用する必要があります。 zZ-07:00と一致しません。これは、RFC 822タイムゾーン形式(-0700)または「一般的なタイムゾーン」(Mountain Standard TimeまたはMSTまたはGMT-07:00)。または、まったく同じタイムゾーン形式を使用して、 JodaTimeの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);
    }
}

上記のコードはすべて Github上 です。自由にクローンを作成してください(他の質問への回答用のコードも入手できます)。

23
Matt Ball

Mattsの回答と非常に似ていますが、Jodaを使用しています。

import Java.lang.reflect.Type;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;

public class DateTimeSerializer implements JsonDeserializer<DateTime> {

    private DateTimeFormatter parser = DateTimeFormat.forPattern("YYYY-MM-dd'T'HH:mm:ss.SS'Z'").withZoneUTC();

    @Override
    public DateTime deserialize(JsonElement json, Type typeOfT,
            JsonDeserializationContext ctx) throws JsonParseException {
        String dateTimeString = ctx.eserialize(json, String.class);
        return parser.parseDateTime(dateTimeString);
    }

}
0
reto