如何正确地将元组序列化为键字典

如何正确地将元组序列化为键字典

本文介绍了如何正确地将元组序列化为键字典的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个以下应用程序,该应用程序显示出字典的关键部分未发送至JsonConverter,但在其上称为ToString().这对我来说是个问题,因为我无法反序列化Json字符串.

I have the following app that shows that the key part of a Dictionary is not sent to JsonConverter, but it is called ToString() on. This is an issue for me as I can't deserialize my Json string .

有什么想法吗?

class Program
{
    static void Main(string[] args)
    {
        var coll = new Dictionary<Tuple<string,string>, string>();
        coll.Add(Tuple.Create("key1", "KEY1"), "Value1");
        coll.Add(Tuple.Create("key2", "KEY2"), "Value2");
        string json = JsonConvert.SerializeObject(coll);
        Dictionary<Tuple<string, string>, string> coll2;
        Console.WriteLine(json);
        //coll2 = JsonConvert.DeserializeObject<Dictionary<Tuple<string, string>, string>>(json);
        // It throws an exception here
        //foreach (var k in coll2)
        //{
        //    Console.WriteLine("<{0}|{1}>",k.Key, k.Value);
        //}

        var t = Tuple.Create("key1", "key2");
        Console.WriteLine(t.ToString());
        string json2 = JsonConvert.SerializeObject(t);
        Console.WriteLine(json2);
    }
}

输出:

推荐答案

在使用Tuple作为键对字典进行反序列化时,我也遇到了同样的问题. JSON将元组转换为纯字符串.但就我而言,我无法避免在字典中使用元组作为键.因此,我制作了一个自定义JSON转换器,以元组为键对字典进行反序列化,并且效果很好.

I also had the same problem with Deserializing a Dictionary with Tuple as key. JSON converts the tuple into a mere string. But in my case, i cannot avoid using Tuple as key in the dictionary. So i made a custom JSON convertor to Deserialize the Dictionary with Tuple as key and it worked well.

我已经按照您的代码进行了修改.希望它能正常工作,并且可以为您提供有关JSON CustomConverter的想法.还可以通过注释更好地解释.

I have modified the same as per your code. Hope it will work fine and can give you an idea about JSON CustomConverter. Also explained better with comments.

public class TupleKeyConverter : JsonConverter
{
    /// <summary>
    /// Override ReadJson to read the dictionary key and value
    /// </summary>
    /// <param name="reader"></param>
    /// <param name="objectType"></param>
    /// <param name="existingValue"></param>
    /// <param name="serializer"></param>
    /// <returns></returns>
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        Tuple<string, string> _tuple = null;
        string _value = null;
        var _dict = new Dictionary<Tuple<string, string>, string>();

        //loop through the JSON string reader
        while (reader.Read())
        {
            // check whether it is a property
            if (reader.TokenType == JsonToken.PropertyName)
            {
                string readerValue = reader.Value.ToString();
                if (reader.Read())
                {
                    // check if the property is tuple (Dictionary key)
                    if (readerValue.Contains('(') && readerValue.Contains(')'))
                    {
                        string[] result = ConvertTuple(readerValue);

                        if (result == null)
                            continue;

                        // Custom Deserialize the Dictionary key (Tuple)
                        _tuple = Tuple.Create<string, string>(result[0].Trim(), result[1].Trim());

                        // Custom Deserialize the Dictionary value
                        _value = (string)serializer.Deserialize(reader, _value.GetType());

                        _dict.Add(_tuple, _value);
                    }
                    else
                    {
                        // Deserialize the remaining data from the reader
                        serializer.Deserialize(reader);
                        break;
                    }
                }
            }
        }
        return _dict;
    }

    /// <summary>
    /// To convert Tuple
    /// </summary>
    /// <param name="_string"></param>
    /// <returns></returns>
    public string[] ConvertTuple(string _string)
    {
        string tempStr = null;

        // remove the first character which is a brace '('
        if (_string.Contains('('))
            tempStr = _string.Remove(0, 1);

        // remove the last character which is a brace ')'
        if (_string.Contains(')'))
            tempStr = tempStr.Remove(tempStr.Length - 1, 1);

        // seperate the Item1 and Item2
        if (_string.Contains(','))
            return tempStr.Split(',');

        return null;
    }

    /// <summary>
    /// WriteJson needs to be implemented since it is an abstract function.
    /// </summary>
    /// <param name="writer"></param>
    /// <param name="value"></param>
    /// <param name="serializer"></param>
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }

    /// <summary>
    /// Check whether to convert or not
    /// </summary>
    /// <param name="objectType"></param>
    /// <returns></returns>
    public override bool CanConvert(Type objectType)
    {
        return true;
    }
}

现在声明一个属性,如下所示. JsonConvertor属性很重要.

Now declare a property as follows. JsonConvertor Property is important.

[JsonConverter(typeof(TupleKeyConverter))]
public Dictionary<Tuple<int,string>,string> MyDict {get; set;}

或者您可以尝试用它替换代码中的内容.尽管我从未测试过.

Or you could try this to replace this in your code. though i never tested.

coll2 = JsonConvert.DeserializeObject<Dictionary<Tuple<string, string>, string>>("", new TupleKeyConverter());

这篇关于如何正确地将元组序列化为键字典的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 10:52