Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
389 views
in Technique[技术] by (71.8m points)

c# - Json.net serialization of custom collection implementing IEnumerable<T>

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 exception System.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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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:

To all future creators of immutable .NET collections: If your collection of T has a constructor that takes IEnumerable then Json.NET will automatically work when deserializing to your collection, otherwise you're all out of luck.

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...