Json.NET反序列化其他类型中的元组不起作用?

使用Json.net,反序列化包含Tuple的类型不起作用(序列化工作,但反序列化不起作用):

 [TestMethod] public void Test() { var orig = new TupleHolder("what????", true); var json = JsonConvert.SerializeObject(orig); Assert.AreEqual("{\"Tup\":{\"Item1\":\"what????\",\"Item2\":true}}", json); // great! serialization works like a charm! now let's test deserialization: var dupl = JsonConvert.DeserializeObject(json); Assert.AreEqual("ZZZ", dupl.Tup.Item1); // pass! but it should be "what????"... what???? Assert.AreEqual(false, dupl.Tup.Item2); // pass! but it should be "true", right??? Assert.AreEqual(orig.Tup.Item1, dupl.Tup.Item1); // fail! Assert.AreEqual(orig.Tup.Item2, dupl.Tup.Item2); // fail! } public class TupleHolder { public Tuple Tup { get; set; } public TupleHolder() { Tup = new Tuple("ZZZ", false); } public TupleHolder(string s, bool b) { Tup = new Tuple(s, b); } } 

有趣的是, Tuple直接反序列化确实有效:

 [TestMethod] public void Test2() { var orig = new Tuple("ABC", true); var json = JsonConvert.SerializeObject(orig); var dupl = JsonConvert.DeserializeObject<Tuple>(json); Assert.AreEqual(orig, dupl); // direct deserialization of Tuple works. } 

这是一个Json.NET错误还是我在这里错过了什么?

无论如何,解决方案 – 或者我的 – 是为元组定义一个自定义转换器。

此示例为特定元组提供了具体的解决方案,但您可以对其进行通用化以使TupleConverter类处理任何值类型的组合。 也可以使它成为抽象的,并且派生类型为每个项实现实例化方法,以处理具有引用类型的元组。

  public class TupleConverter : Newtonsoft.Json.JsonConverter { public override bool CanConvert(Type objectType) { return typeof(Tuple) == objectType; } public override object ReadJson( Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { if (reader.TokenType == Newtonsoft.Json.JsonToken.Null) return null; var jObject = Newtonsoft.Json.Linq.JObject.Load(reader); var target = new Tuple( (string)jObject["Item1"], (bool)jObject["Item2"]); return target; } public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { serializer.Serialize(writer, value); } } public class TupleHolder { [Newtonsoft.Json.JsonConverter(typeof(TupleConverter))] public Tuple Tup { get; set; } public TupleHolder() { Tup = new Tuple("ZZZ", false); } public TupleHolder(string s, bool b) { Tup = new Tuple(s, b); } } [Test] public void Test() { var orig = new TupleHolder("what????", true); var json = Newtonsoft.Json.JsonConvert.SerializeObject(orig); Assert.AreEqual("{\"Tup\":{\"Item1\":\"what????\",\"Item2\":true}}", json); var dupl = Newtonsoft.Json.JsonConvert.DeserializeObject(json); // These succeed, now Assert.AreEqual(orig.Tup.Item1, dupl.Tup.Item1); Assert.AreEqual(orig.Tup.Item2, dupl.Tup.Item2); } 

雷米提供的答案帮助了我。 我拿了他的TupleConverter并使其成为2元组的通用。 任何N元组的概念都是相同的。

我把它留在这里,以防它帮助某人。

 public class TupleConverter : Newtonsoft.Json.JsonConverter { public override bool CanConvert(Type objectType) { return typeof(Tuple) == objectType; } public override object ReadJson( Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { if (reader.TokenType == Newtonsoft.Json.JsonToken.Null) return null; var jObject = Newtonsoft.Json.Linq.JObject.Load(reader); var target = new Tuple( jObject["m_Item1"].ToObject(), jObject["m_Item2"].ToObject()); return target; } public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { serializer.Serialize(writer, value); } } 

注意:我的元组是用m_Item1m_Item2序列化的JSON,所以我不得不将jObject["ItemX"]更改为jObject["m_ItemX"]

List>用法示例:

 string result = "String to deserialize"; JsonSerializerSettings settings = new JsonSerializerSettings(); settings.Converters.Add(new TupleConverter()); List> users = JsonConvert.DeserializeObject>>(result, settings);