当前位置: 首页 > 面试题库 >

如何处理多态反序列化?

乐正意智
2023-03-14
问题内容

我有一个像这样的课程:

public class Barn {
    String type;
    Animal animal;
}

public class Horse extends Animal {
}

public class Cow extends Animal {
}

我想序列化它们的列表:

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);

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

谢谢


问题答案:

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<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 {}


 类似资料:
  • 我在Spring Kafka设置中使用Avro和模式注册表。 我想以某种方式处理,它可能在反序列化过程中引发。 我找到了以下两个资源: https://github.com/spring-projects/spring-kafka/issues/164 有人知道如何在Spring Boot中捕获吗? 我使用的是Spring Boot 2.0.2 编辑:我找到了解决办法。

  • 我对Jackson和类型层次结构有以下问题。我正在序列化一个类SubA,该类将扩展为一个字符串,然后尝试将其反序列化回来。当然,在编译时,系统不知道它是基还是SubA,因此我希望它是基,如果它是SubA,则会在编译后执行一些其他操作。 我的基本类看起来像: ...和一个派生自的类: ... 我试图执行以下代码: String是: 但我一次又一次地犯同样的错误。映射器现在知道如何处理另一个类参数-它

  • 问题内容: 我有一个Vendor对象,可以从一个单独的“ vendor” json序列中反序列化,但是我想将此序列反序列化为一个,我只是想不出如何让Jackson合作。有小费吗? 问题答案: 您的数据存在问题,因为您的数组中有内部 包装 对象。想必你的对象被设计成手柄,,,但每次的多个对象也都包裹在一个对象与单一属性。 我假设您正在使用Jackson 数据绑定 模型。 如果是这样,那么有两件事要考

  • 我想为我们的REST API实现一个自定义的反序列化器,它不仅被Java应用程序使用。因此,我不想让Jackson将类型信息放入序列化的JSON中。 我目前正在努力反序列化<code>CollectionExpand</code>,因为它包含特定<code>ResourceModel</code>的<code>数据</code>列表。 < code>ResourceModel是一个接口,每个< c

  • 如何在批处理模式的情况下处理反序列化异常? 我正在使用Spring boot-2.3.8版本的Spring kafka。 尝试过此选项: 但它抛出了一个异常:由java引起。lang.IllegalStateException:错误处理程序必须是ErrorHandler,而不是org。springframework。Kafka。听众。请参阅OcuCurrentBatchErrorHandler 以

  • 我有一个接口,其中和实现。服务器会返回这样的响应- 相应的类来建模它是 中的声明它是哪种车辆。我需要反序列化的成一个对象取决于。如果是,我需要在反序列化和期间使用反序列化。 如何使用gson实现这一点? 编辑-这篇文章的不同之处在于类类型()包含在需要反序列化的中。这里不是。如果在内,我可以为编写自定义反序列化程序,检查,并进行相应的反序列化。但是我想我需要为编写一个自定义反序列化程序,在这里我创