How to properly serialize tuple as key dictionary

前端 未结 2 1033
一生所求
一生所求 2021-01-19 21:39

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 issu

相关标签:
2条回答
  • 2021-01-19 22:22

    Based on the information you have provided, I would suggest that instead of using a Tuple as your key, use a custom struct or object and override the ToString method. Then you can serialize/deserialize as you wish.

    0 讨论(0)
  • 2021-01-19 22:33

    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.

    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;
        }
    }
    

    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());
    
    0 讨论(0)
提交回复
热议问题