Tuple的Json.NET反序列化...里面的另一种类型不起作用? [英] Json.NET deserialization of Tuple<...> inside another type doesn't work?

查看:339
本文介绍了Tuple的Json.NET反序列化...里面的另一种类型不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Json.net,反序列化包含Tuple<...>的类型不起作用(序列化有效,但是反序列化无效):

Using Json.net, deserializing a type that contains a Tuple<...> doesn't work (serialization works, but deserialization doesn't):

[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<TupleHolder>(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<string, bool> Tup { get; set; }
    public TupleHolder() { Tup = new Tuple<string, bool>("ZZZ", false); }
    public TupleHolder(string s, bool b) { Tup = new Tuple<string, bool>(s, b); }
}

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

Funny thing is that direct deserialization of Tuple<...> does work:

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

这是Json.NET错误还是我在这里遗漏了一些东西?

Is it a Json.NET bug or am I missing here something?

推荐答案

解决方案-还是我的解决方案-是为元组定义一个自定义转换器.

The solution - or mine, anyhow - is to define a custom converter for the Tuple.

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

This example provides a concrete solution for a specific Tuple, but you could genericize it to make the TupleConverter class to handle any combination of value types. Could also make it abstract and have derived types implement instantiation methods for each item, to handle tuples with reference types.

    public class TupleConverter : Newtonsoft.Json.JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(Tuple<string, bool>) == 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, bool>(
                (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<string, bool> Tup { get; set; }
        public TupleHolder() { Tup = new Tuple<string, bool>("ZZZ", false); }
        public TupleHolder(string s, bool b) { Tup = new Tuple<string, bool>(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<TupleHolder>(json);

        // These succeed, now
        Assert.AreEqual(orig.Tup.Item1, dupl.Tup.Item1);
        Assert.AreEqual(orig.Tup.Item2, dupl.Tup.Item2);
    }

这篇关于Tuple的Json.NET反序列化...里面的另一种类型不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆