简体   繁体   中英

How to solve Gson deserialization issue of polymorphism of java.lang objects

I was using gson for deserialization. My class has an instance field which is an Object type because some time it can be instantiated with String or Date object. But up on deserialization, I am not able to get it as Date or String type. I understood that there is a solution using RuntimeTypeAdapterFactory but I can not use that because I can not add a RuntimeTypeAdapterFactory solution ( https://futurestud.io/tutorials/how-to-deserialize-a-list-of-polymorphic-objects-with-gson ) because I can not add 'type' field to java.lang.String or java.util.Date.

Is there any way I can solve this issue?

Please see sample code for this issue

import java.lang.reflect.Type;
import java.text.SimpleDateFormat;

import java.util.Date;


import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
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;
import com.google.gson.reflect.TypeToken;

public class GsonSer {

    String name;
     Object dob;

    public GsonSer(String name, Date dob) {
        this.name = name;
        this.dob = dob;
    }

    static class JsonDateSerDeserializer implements JsonSerializer<Date>, JsonDeserializer<Date> {

        @Override
        public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {

            return new JsonPrimitive(src.getTime());
        }

        @Override
        public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                throws JsonParseException {
            Date parsed = new Date(json.getAsLong());
            return parsed;
        }

    }

    public static void main(String[] args) {
        GsonSer ser = new GsonSer("name", new Date());
     Type DATE_TYPE = new TypeToken<Date>() {
        }.getType();
        Gson gson = new GsonBuilder().registerTypeAdapter(DATE_TYPE, new JsonDateSerDeserializer())
                .create();
        String date = gson.toJson(ser);
        System.out.println("Original = " + ser.dob + "\n");
        GsonSer deser = gson.fromJson(date, GsonSer.class);
        System.out.println("after deser = " + deser.dob + "\n");

    }
}

//output

original = Thu Aug 09 10:13:24 CEST 2018

after deser = 1.533802404071E12

A distinct non-answer: don't do that.

The point of such "beans" is to act as "transport" vehicle. This means that you should really know exactly what gets transported. If you need to deal with multiple types, make that part of the interface that the bean class offers.

Meaning:

  • decide for one class to be used as type of that field. I would go with String for flexibility. Object is not a good idea!
  • provide getter/setters that allow you to set/retrieve Date objects as well

In other words: don't try to get gson to resolve ambiguity for you.

Simple avoid the ambiguity within the bean, so you can use gson without any kind of special setup. Have the bean contain a String (ideally you would informally specify allowed formats ), and enable the bean to also accept Date/Instant/Whatever objects that represent date/time).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM