Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实现IEnumerable的自定义集合的Json.net序列化<;T>;_C#_Json_Serialization_Json.net - Fatal编程技术网

C# 实现IEnumerable的自定义集合的Json.net序列化<;T>;

C# 实现IEnumerable的自定义集合的Json.net序列化<;T>;,c#,json,serialization,json.net,C#,Json,Serialization,Json.net,我有一个实现IEnumerable的集合类,但反序列化该类的序列化版本时遇到问题。我使用的是Json.NETV4.0.2.13623 下面是我的collection类的一个更简单的版本,它说明了我的问题 public class MyType { public int Number { get; private set; } public MyType(int number) { this.Number = number; } } public class MyType

我有一个实现IEnumerable的集合类,但反序列化该类的序列化版本时遇到问题。我使用的是Json.NETV4.0.2.13623

下面是我的collection类的一个更简单的版本,它说明了我的问题

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
  }
}
但是当我尝试反序列化时,我得到了以下异常 系统异常:无法创建和填充列表类型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<MyTypes>(_jsonContent, _serializationSettings);
}
public void往返()
{
var_myTypes1=新的MyTypes(new[]{new MyType(1),new MyType(2)});
var _jsonContent=JsonConvert.serialized对象(_myTypes1,Formatting.Indented);
var _myTypes2=JsonConvert.DeserializeObject(_jsonContent);
}
公共无效RoundTripWithSettings()
{
var_myTypes1=新的MyTypes(new[]{new MyType(1),new MyType(2)});
var_serializationSettings=newjsonserializersettings{typenameholding=typenameholding.Arrays};
var _jsonContent=JsonConvert.SerializeObject(_myTypes1,Formatting.Indented,_serializationSettings);
var\u myTypes2=JsonConvert.DeserializeObject(\u jsonContent,\u serializationSettings);
}
有人成功地序列化了他们自己的集合对象吗

提前谢谢


Pat

我认为JSON.NET依赖于为其反序列化到的类型提供无参数构造函数。从反序列化的角度来看,它不知道应该向构造函数提供什么

至于您的集合,它应该如何知道如何填充
IEnumerable
的实现,该实现只定义如何枚举集合,而不定义如何填充集合。相反,您应该直接反序列化到一些标准的
IEnumerable
(或者直接反序列化到我认为JSON.NET支持的
IEnumerable
),然后将其传递给构造函数

我认为,在这种情况下,以下所有方面都应该起作用:

var _myTypes2 = new MyTypes(JsonConvert.DeserializeObject<MyTypes[]>(_jsonContent));
var _myTypes2 = new MyTypes(JsonConvert.DeserializeObject<List<MyTypes>>(_jsonContent));
var _myTypes2 = new MyTypes(JsonConvert.DeserializeObject<IEnumerable<MyTypes>>(_jsonContent));
var\u myTypes2=新的MyTypes(jsoninvert.DeserializeObject(\u jsonContent));
var_myTypes2=新的MyTypes(JsonConvert.DeserializeObject(_jsonContent));
var_myTypes2=新的MyTypes(JsonConvert.DeserializeObject(_jsonContent));

或者,尽管需要做更多的工作,但如果需要直接反序列化,您可以在集合上实现类似IList的功能,这将允许JSON.NET使用IList方法填充集合。

从JSON.NET 6.0版本3及更高版本开始(我在8.0.3上进行了测试),只要实现
IEnumerable
的自定义类有一个接受
IEnumerable
输入参数的构造函数,该函数就会自动工作。从:

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

因为问题中的
MyTypes
类正好有这样一个构造函数,所以现在就可以了。示范小提琴:


如果没有这样的构造函数,则需要添加一个无参数构造函数,并使用一个工作的
add(MyType项)
方法实现
ICollection
(而不仅仅是
IEnumerable
)。然后,Json.NET可以构造并填充集合。或者反序列化到中间集合,如中所示。

您应该序列化并反序列化到具体集合,如列表,而不是IEnumerable。为了反序列化某些东西,它需要一个实现,而不仅仅是一个接口。Chris,通过一些其他更改更改为ReadOnlyCollection的子类,但我知道反序列化集合实际上也可以使用IList。它将为您创建一个列表。但是没有为IEnumerable定义默认集合。由于这个答案,库扩展了它的功能-它将使用无参数构造函数(一如既往)但它还支持创建一个实例,该实例通过构造函数获取其所有数据,并支持具有采用IEnumerable的构造函数的集合类型(正如@dbc提到的答案)。
var _myTypes2 = new MyTypes(JsonConvert.DeserializeObject<MyTypes[]>(_jsonContent));
var _myTypes2 = new MyTypes(JsonConvert.DeserializeObject<List<MyTypes>>(_jsonContent));
var _myTypes2 = new MyTypes(JsonConvert.DeserializeObject<IEnumerable<MyTypes>>(_jsonContent));