本文介绍了实现 IEnumerable<T> 的自定义集合的 Json.net 序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个实现 IEnumerable 的集合类,但在反序列化它的序列化版本时遇到了麻烦.我正在使用 Json.net v 4.0.2.13623

这是我的集合类的一个更简单的版本,它说明了我的问题

公共类 MyType{public int Number { 得到;私人订制;}公共 MyType(整数){this.Number = 数字;}}公共类 MyTypes : IEnumerable{private readonly Dictionaryc_index;公共 MyTypes(IEnumerable 种子){this.c_index = seed.ToDictionary(item => item.Number);}公共 IEnumerator获取枚举器(){返回 this.c_index.Values.GetEnumerator();}IEnumerator IEnumerable.GetEnumerator(){返回 this.GetEnumerator();}公共 int CustomMethod(){返回 1;//只是为了说明}}

当我序列化它时,我得到以下 json

[{1号},{2号}]

但是当我尝试反序列化时,出现以下异常System.Exception:无法创建和填充列表类型 MyTypes

也曾尝试使用序列化提示但没有成功

这些是我用过的测试函数

public void RoundTrip(){var _myTypes1 = new MyTypes(new[] { new MyType(1), new MyType(2) });var _jsonContent = JsonConvert.SerializeObject(_myTypes1, Formatting.Indented);var _myTypes2 = JsonConvert.DeserializeObject<MyTypes>(_jsonContent);}public void RoundTripWithSettings(){var _myTypes1 = new MyTypes(new[] { new MyType(1), new MyType(2) });var _serializationSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Arrays };var _jsonContent = JsonConvert.SerializeObject(_myTypes1, Formatting.Indented, _serializationSettings);var _myTypes2 = JsonConvert.DeserializeObject(_jsonContent, _serializationSettings);}

有没有人设法序列化他们自己的集合对象?

提前致谢

解决方案

从 Json.NET 6.0 Release 3 及更高版本开始(我在 8.0.3 上测试过),只要自定义类实现了 IEnumerable<MyType> 有一个构造函数,它接受一个 IEnumerable 输入参数.来自 发行说明:

致所有未来不可变 .NET 集合的创建者:如果您的 T 集合有一个接受 IEnumerable 的构造函数,那么在反序列化到您的集合时,Json.NET 将自动工作,否则您就走运了.

由于问题中的 MyTypes 类具有这样的构造函数,所以现在 可以正常工作.演示小提琴:https://dotnetfiddle.net/LRJHbd.

如果没有这样的构造函数,就需要添加一个无参数的构造函数并用一个有效的实现ICollection(而不仅仅是IEnumerable)>Add(MyType item) 方法.然后 Json.NET 可以构造和填充集合.或者反序列化为中间集合,如原始答案.

I have a collection class that implements IEnumerable and I am having trouble deserializing a serialized version of the same. I am using Json.net v 4.0.2.13623

Here is a simplier version of my collection class that illustrates my issue

public class MyType
{
  public int Number { get; private set; }
  public MyType(int number)
  {
    this.Number = number;
  }
}

public class MyTypes : IEnumerable<MyType>
{
  private readonly Dictionary<int, MyType> c_index;
  public MyTypes(IEnumerable<MyType> seed)
  {
    this.c_index = seed.ToDictionary(item => item.Number);
  }
  public IEnumerator<MyType> GetEnumerator()
  {
    return this.c_index.Values.GetEnumerator();
  }
  IEnumerator IEnumerable.GetEnumerator()
  {
    return this.GetEnumerator();
  }
  public int CustomMethod()
  {
    return 1;  // Just for illustration
  }
}

When I serialize it i get the following json

[
  {
    "Number": 1
  },
  {
    "Number": 2
  }
]

But then when i try to deserialize i get the following exceptionSystem.Exception: Cannot create and populate list type MyTypes

Have also tried using serialization hints but have had no success

These are the test function i have used

public void RoundTrip()
{
  var _myTypes1 = new MyTypes(new[] { new MyType(1), new MyType(2) });
  var _jsonContent = JsonConvert.SerializeObject(_myTypes1, Formatting.Indented);
  var _myTypes2 = JsonConvert.DeserializeObject<MyTypes>(_jsonContent);
}
public void RoundTripWithSettings()
{
  var _myTypes1 = new MyTypes(new[] { new MyType(1), new MyType(2) });

  var _serializationSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Arrays };
  var _jsonContent = JsonConvert.SerializeObject(_myTypes1, Formatting.Indented, _serializationSettings);
  var _myTypes2 = JsonConvert.DeserializeObject<MyTypes>(_jsonContent, _serializationSettings);
}

Has anybody managed to serialize their own collection objects ?

Thanks in advance

Pat

解决方案

As of Json.NET 6.0 Release 3 and later (I tested on 8.0.3), this works automatically as long as the custom class implementing IEnumerable<MyType> has a constructor that takes an IEnumerable<MyType> input argument. From the release notes:

Since the MyTypes class in the question has just such a constructor, this now just works. Demonstration fiddle: https://dotnetfiddle.net/LRJHbd.

Absent such a constructor, one would need to add a parameterless constructor and implement ICollection<MyType> (instead of just IEnumerable<MyType>) with a working Add(MyType item) method. Json.NET can then construct and populate the collection. Or deserialize to an intermediate collection as in the original answer.

这篇关于实现 IEnumerable&lt;T&gt; 的自定义集合的 Json.net 序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 11:15