Recursively call JsonSerializer in a JsonConverter

后端 未结 3 573
一个人的身影
一个人的身影 2020-12-11 00:40

I\'m writing a JsonConverter to perform some conversion tasks I need accomplished on read/write. In particular, I\'m taking the existing serialization behavior

3条回答
  •  情书的邮戳
    2020-12-11 01:15

    This is a very common problem. Using "JsonConvert.SerializeObject" isn't a bad idea. However, one trick that can be used in some circumstances (typically collections) is to cast to the interface when writing and deserialize to a simple derivative when reading.

    Below is a simple converter that deals with dictionaries that might have been serialized as a set of KVPs rather than looking like an object (showing my age here :) )

    Note "WriteJson" casts to IDictionary< K,V> and "ReadJson" uses "DummyDictionary". You end up with the right thing but uses the passed serializer without causing recursion.

    /// 
    /// Converts a  to and from JSON.
    /// 
    public class DictionaryAsKVPConverter : JsonConverter
    {
        /// 
        /// Determines whether this instance can convert the specified object type.
        /// 
        /// Type of the object.
        /// 
        ///     true if this instance can convert the specified object type; otherwise, false.
        /// 
        public override bool CanConvert(Type objectType)
        {
            if (!objectType.IsValueType && objectType.IsGenericType)
                return (objectType.GetGenericTypeDefinition() == typeof(Dictionary<,>));
    
            return false;
        }
    
        /// 
        /// Writes the JSON representation of the object.
        /// 
        /// The  to write to.
        /// The value.
        /// The calling serializer.
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var dictionary = value as IDictionary;
            serializer.Serialize(writer, dictionary);
        }
    
        /// 
        /// Reads the JSON representation of the object.
        /// 
        /// The  to read from.
        /// Type of the object.
        /// The existing value of object being read.
        /// The calling serializer.
        /// The object value.
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            Dictionary dictionary;
    
            if (reader.TokenType == JsonToken.StartArray)
            {
                dictionary = new Dictionary();
                reader.Read();
                while (reader.TokenType == JsonToken.StartObject)
                {
                    var kvp = serializer.Deserialize>(reader);
                    dictionary[kvp.Key] = kvp.Value;
                    reader.Read();
                }
            }
            else if (reader.TokenType == JsonToken.StartObject)
                // Use DummyDictionary to fool JsonSerializer into not using this converter recursively
                dictionary = serializer.Deserialize(reader);
            else
                dictionary = new Dictionary();
    
            return dictionary;
        }
    
        /// 
        /// Dummy to fool JsonSerializer into not using this converter recursively
        /// 
        private class DummyDictionary : Dictionary { }
    }
    

提交回复
热议问题