简体   繁体   English

gson序列化和反序列化ArrayList <object>

[英]gson serialization and deserialization of an ArrayList<object>

My set up is like so: 我的设置是这样的:

public enum AnimalType {
  CAT(1),
  DOG(2);

  private final int value;
  AnimalType(int value) {
    this.value = value;
  }
  public int value() { return value; }
}

public class Dog {
  AnimalType type = AnimalType.DOG;
  String name;
  int id;
  //Other properties. Point is to distinguish it from a Cat object.
}

public class Cat {
  AnimalType type = AnimalType.CAT;
  String name;
  String nickName;
  int age;
}

public class Response {
  ArrayList<Object> myResponseObject;
}

Here's an example of how a Response object might look: 以下是Response对象的外观示例:

ArrayList<Object> arr = new ArrayList<Object>();
Dog dog = new Dog("MyName",0);
Cat cat = new Cat("MyName","MyNickName",-1);

arr.add("I have a ");
arr.add(cat)
arr.add(" and a ");
arr.add(dog)
Response response = new Response(arr);

and I am serializing like so: 我这样序列化:

Gson gson = new Gson();
String serializedOutput = gson.toJson(response);

and hope to deserialize like so: 并希望像这样反序列化:

//the ArrayList<Object> should be populated correctly inside of it?
Response deserializedObject = gson.fromJson(serializedOutput);

However, on deserializing this list, I need the objects to map back to their respective types. 但是,在反序列化此列表时,我需要将对象映射回各自的类型。 I suspect I need to at least tag the class or type into my serialization of Dog or Cat. 我怀疑我至少需要标记该类或输入我的狗或猫的序列化。 For now, I am adding a Type property (instead of interface) on Dog and Cat. 现在,我在Dog和Cat上添加了一个Type属性(而不是interface)。

Without anything fancy, the Cat and Dog objects are by default treated as LinkedTreeMap<K,V> when deserialized. 没有任何花哨的东西, CatDog对象在反序列化时默认被视为LinkedTreeMap<K,V> I have to iterate through my arraylist, check if it is an instanceof LinkedTreeMap, call the "type" key to get the type, and then cast my object to Dog or Cat. 我必须遍历我的arraylist,检查它是否是LinkedTreeMap的实例,调用“type”键来获取类型,然后将我的对象转换为Dog或Cat。 This all just seems a bit hacky to me, and I'm wondering if there's a more elegant way to do this. 这一切对我来说似乎有些苛刻,我想知道是否有更优雅的方式来做到这一点。

Should I be using a custom serializer/deserializer for my Cat/Dog objects or is the RuntimeTypeAdapterFactory the way to go? 我应该为我的Cat / Dog对象使用自定义序列化器/反序列化器,还是RuntimeTypeAdapterFactory要走的路? Any guidance would be appreciated. 任何指导将不胜感激。

Note, I'm also custom serializing/deserializing my enum by following the directions from Gson: How to change output of Enum . 注意,我也是按照Gson的指示自定义/反序列化我的枚举:如何更改枚举的输出 I'm not sure whether that affects anything. 我不确定这是否会影响任何事情。

Thanks 谢谢

This is covered in the users guide. 用户指南中对此进行了介绍。 You are attempting to deserialize a collection of arbitrary types 您正在尝试反序列化任意类型的集合

As noted there, you have 3 options: 如上所述,您有3个选择:

Option 1: Use Gson's parser API (low-level streaming parser or the DOM parser JsonParser) to parse the array elements and then use Gson.fromJson() on each of the array elements.This is the preferred approach. 选项1:使用Gson的解析器API(低级流解析器或DOM解析器JsonParser)来解析数组元素,然后在每个数组元素上使用Gson.fromJson()。这是首选方法。

Option 2: Register a type adapter for Collection.class that looks at each of the array members and maps them to appropriate objects. 选项2:为Collection.class注册一个类型适配器,它查看每个数组成员并将它们映射到适当的对象。 The disadvantage of this approach is that it will screw up deserialization of other collection types in Gson. 这种方法的缺点是它会搞砸Gson中其他集合类型的反序列化。

Option 3: Register a type adapter for MyCollectionMemberType and use fromJson with Collection<MyCollectionMemberType> This approach is practical only if the array appears as a top-level element or if you can change the field type holding the collection to be of type Collection<MyCollectionMemberType>. 选项3:为MyCollectionMemberType注册类型适配器并使用fromJson与Collection <MyCollectionMemberType>仅当数组显示为顶级元素或者您可以将包含集合的字段类型更改为Collection <MyCollectionMemberType类型时,此方法才可用>。

This is a difficult problem when talking about automatic deserialization. 在谈论自动反序列化时,这是一个难题。 In addition, option 3 isn't possible in your case as you're using Object rather than having Dog and Cat inherit from some base class (eg Animal ). 此外,在您的情况下,选项3是不可能的,因为您正在使用Object而不是让DogCat继承自某些基类(例如Animal )。

On top of that ... you're doing something very odd with that array of Objects, sticking String s in it as well. 最重要的是......你正在用这些对象做一些非常奇怪的东西,并在其中粘贴String Overall, if that's some response you yourself are generating ... I'd seriously rethink how you're approaching that. 总的来说,如果这是你自己产生的一些反应......我会认真地重新思考你是如何接近这一点的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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