如何处理多态的反序列化? [英] How to handle deserializing with polymorphism?

查看:246
本文介绍了如何处理多态的反序列化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类:

$ p $ public class Barn {
String type;
动物动物;
}

public class Horse extends Animal {
}

public class Cow extends Animal {
}

我想序列化它们的列表:

 列表与LT;谷仓> barns = new ArrayList< Barn>(); 

Barn barn1 =新Barn();
barn1.setType(horse);
barn1.setAnimal(new Horse());
barns.add(barn1);

Barn barn2 =新Barn();
barn2.setType(cow);
barn2.setAnimal(new Cow());
barns.add(barn2);

...

组< Barn>谷仓= gson.fromJson(序列化);

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



谢谢

解决方案

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



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

  import java.lang.reflect。类型; 
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(),新的谷仓()};
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 =新的BarnDeserializer(type);
deserializer.registerBarnType(horse,Horse.class);
deserializer.registerBarnType(cow,Cow.class);
Gson gson = new GsonBuilder()。registerTypeAdapter(Barn.class,deserializer).create();

列表< Barn> barns2 = gson.fromJson(json,new TypeToken< List< Barn>>(){}。getType());
for(Barn barn:barns2)
{
System.out.println(barn.animal.getClass());
}
}
}

class BarnDeserializer实现了JsonDeserializer< Barn>
{
字符串barnTypeElementName;
Gson gson;
地图< String,Class< ;?延伸动物>> barnTypeRegistry;

BarnDeserializer(String barnTypeElementName)
{
this.barnTypeElementName = barnTypeElementName;
gson = new Gson();
barnTypeRegistry = new HashMap<>(); //此语法需要Java 7。


void registerBarnType(String barnTypeName,Class <?extends Animal> animalType)
{
barnTypeRegistry.put(barnTypeName,animalType);

$ b @Override
public Barn反序列化(JsonElement json,类型typeOfT,JsonDeserializationContext上下文)
抛出JsonParseException
{
JsonObject barnObject = json.getAsJsonObject();
JsonElement animalTypeElement = barnObject.get(barnTypeElementName);
Barn barn =新Barn();
barn.type = animalTypeElement.getAsString();
Class <?延伸动物> animalType = barnTypeRegistry.get(barn.type);
barn.animal = gson.fromJson(barnObject.get(animal),animalType);
返回谷仓;
}
}

class Barn {String type;动物动物;}
class Animal {}
class Horse extends Animal {}
class Cow extends Animal {}


I have a class like:

public class Barn {
    String type;
    Animal animal;
}

public class Horse extends Animal {
}

public class Cow extends Animal {
}

and I want to serialize a list of them:

List<Barn> barns = new ArrayList<Barn>();

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<Barn> barns = gson.fromJson(serialized);   

When I serialize, type information will be lost for the Animal attribute. Is there a way I could install a parser listener somehow so that I could provide the right class to deserialize as when each element in the list is encountered? That was the idea behind manually supplying a string describing the class type.

Thanks

解决方案

In the Gson project code base is the RuntimeTypeAdapter, which reportedly works well for polymorphic serialization and deserialization. I don't think I've yet tried to use it. See http://code.google.com/p/google-gson/issues/detail?id=231 for more info. Note, it hasn't yet been included in any Gson releases.

If use of it doesn't fit your needs, then custom deserialization processing is necessary. Following is one such approach, assuming you want to use the JSON structure demonstrated. (I'd take a somewhat different approach, if the JSON structure could be different.)

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<Barn> barns2= gson.fromJson(json, new TypeToken<List<Barn>>(){}.getType());
    for (Barn barn : barns2)
    {
      System.out.println(barn.animal.getClass());
    }
  }
}

class BarnDeserializer implements JsonDeserializer<Barn>
{
  String barnTypeElementName;
  Gson gson;
  Map<String, Class<? extends Animal>> barnTypeRegistry;

  BarnDeserializer(String barnTypeElementName)
  {
    this.barnTypeElementName = barnTypeElementName;
    gson = new Gson();
    barnTypeRegistry = new HashMap<>(); // Java 7 required for this syntax.
  }

  void registerBarnType(String barnTypeName, Class<? extends Animal> 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<? extends Animal> 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 {}

这篇关于如何处理多态的反序列化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆