如何处理多态的反序列化?

我有一个类:

public class Barn { String type; Animal animal; } public class Horse extends Animal { } public class Cow extends Animal { } 

我想序列化它们的列表:

 List barns = new ArrayList(); Barn barn1 = new Barn(); barn1.setType("horse"); barn1.setAnimal(new Horse()); barns.add(barn1); Barn barn2 = new Barn(); barn2.setType("cow"); barn2.setAnimal(new Cow()); barns.add(barn2); ... Group barns = gson.fromJson(serialized); 

当我序列化时,类型信息将丢失Animal属性。 有没有办法我可以以某种方式安装解析器监听器,以便我可以提供正确的类反序列化,因为遇到列表中的每个元素? 这就是手动提供描述类类型的字符串的想法。

谢谢

在Gson项目中,代码库是RuntimeTypeAdapter ,据报道它适用于多态序列化和反序列化。 我认为我还没有尝试过使用它。 有关详细信息,请参阅http://code.google.com/p/google-gson/issues/detail?id=231 。 请注意,它尚未包含在任何Gson版本中。

如果使用它不符合您的需求,则需要进行自定义反序列化处理。 以下是一种这样的方法,假设您要使用演示的JSON结构。 (如果JSON结构可能不同,我会采用一种不同的方法。)

 import java.lang.reflect.Type; import java.util.HashMap; import java.util.List; import java.util.Map; 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.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; public class App { public static void main(String[] args) { Barn[] barns = {new Barn(), new Barn()}; barns[0].type = "horse"; barns[0].animal = new Horse(); barns[1].type = "cow"; barns[1].animal = new Cow(); String json = new Gson().toJson(barns); // [{"type":"horse","animal":{}},{"type":"cow","animal":{}}] BarnDeserializer deserializer = new BarnDeserializer("type"); deserializer.registerBarnType("horse", Horse.class); deserializer.registerBarnType("cow", Cow.class); Gson gson = new GsonBuilder().registerTypeAdapter(Barn.class, deserializer).create(); List barns2= gson.fromJson(json, new TypeToken>(){}.getType()); for (Barn barn : barns2) { System.out.println(barn.animal.getClass()); } } } class BarnDeserializer implements JsonDeserializer { String barnTypeElementName; Gson gson; Map> barnTypeRegistry; BarnDeserializer(String barnTypeElementName) { this.barnTypeElementName = barnTypeElementName; gson = new Gson(); barnTypeRegistry = new HashMap<>(); // Java 7 required for this syntax. } void registerBarnType(String barnTypeName, Class animalType) { barnTypeRegistry.put(barnTypeName, animalType); } @Override public Barn deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject barnObject = json.getAsJsonObject(); JsonElement animalTypeElement = barnObject.get(barnTypeElementName); Barn barn = new Barn(); barn.type = animalTypeElement.getAsString(); Class animalType = barnTypeRegistry.get(barn.type); barn.animal = gson.fromJson(barnObject.get("animal"), animalType); return barn; } } class Barn {String type; Animal animal;} class Animal {} class Horse extends Animal {} class Cow extends Animal {} 

你可以使用Gson Fire 。 代码看起来像这样:

 GsonFireBuilder builder = new GsonFireBuilder() .registerTypeSelector(Barn.class, new TypeSelector() { @Override public Class getClassForElement(JsonElement readElement) { String type = readElement.getAsJsonObject().get("type").getAsString(); if(type.equals("horse")){ return Horse.class; } else if(type.equals("cow")) { return Cow.class; } else { return null; //returning null will trigger Gson's default behavior } } }); Gson gson = builder.createGson(); 

我也对这个function感兴趣,并且我已经向GSon添加了一个function请求

https://github.com/google/gson/issues/869

您不需要编写自己的适配器。

最后gson有自己的RuntimeTypeAdapterFactory来处理java多态,但不幸的是它不是gson核心库的一部分(为了使用它,你必须将类复制并粘贴到你的项目中)。

假设你有这个Animal.class

 public class Animal { protected String name; protected String type; public Animal(String name, String type) { this.name = name; this.type = type; } } 

Horse.class

 public class Horse extends Animal { public Horse(String name) { super(name, "horse"); } } 

您可以使用以下代码初始化RuntimeTypeAdapterFactory

 RuntimeTypeAdapterFactory runtimeTypeAdapterFactory = RuntimeTypeAdapterFactory .of(Animal.class, "type") .registerSubtype(Horse.class, "horse") .registerSubtype(Cow.class, "cow"); Gson gson = new GsonBuilder() .registerTypeAdapterFactory(runtimeTypeAdapterFactory) .create(); 

在这里您可以找到一个完整的工作示例。