Json.NET - Default deserialization behavior for a single property in CustomCreationConverter

前端 未结 1 1955
借酒劲吻你
借酒劲吻你 2021-02-20 13:49

In the following scenario, how do I get CrazyItemConverter to carry on as usual when it encounters a JSON property that exists in the type I\'m deserializing to?

相关标签:
1条回答
  • 2021-02-20 14:31

    If I'm understanding correctly, your CrazyItemConverter exists so that you can deserialize known properties in the JSON to strongly-typed properties, while still preserving "extra" fields that may be in the JSON into dictionary.

    It turns out that Json.Net already has this feature built in (since 5.0 release 5), so you don't need a crazy converter. Instead, you just need to mark your dictionary with the [JsonExtensionData] attribute. (See the author's blog for more information.)

    So your Item class would look like this:

    public class Item
    {
        [JsonConverter(typeof(CrazyStringConverter))]
        public string Name { get; set; }
    
        public Guid? Id { get; set; }
    
        [JsonExtensionData]
        public Dictionary<string, object> CustomFields
        {
            get
            {
                if (_customFields == null)
                    _customFields = new Dictionary<string, object>();
                return _customFields;
            }
            private set
            {
                _customFields = value;
            }
        }
        private Dictionary<string, object> _customFields;
    }
    

    Then you can just deserialize it as normal. Demo:

    class Program
    {
        static void Main(string[] args)
        {
            string json = @"
            {
                ""Item"":
                {
                    ""Name"":""Apple"",
                    ""Id"":""4b7e9f9f-7a30-4f79-8e47-8b50ea26ddac"",
                    ""Size"":5,
                    ""Quality"":2
                }
            }";
    
            Item item = JsonConvert.DeserializeObject<Wrapper>(json).Item;
            Console.WriteLine("Name: " + item.Name);
            Console.WriteLine("Id: " + item.Id);
            foreach (KeyValuePair<string, object> kvp in item.CustomFields)
            {
                Console.WriteLine(kvp.Key + ": " + kvp.Value);
            }
        }
    }
    
    public class Wrapper
    {
        public Item Item { get; set; }
    }
    
    class CrazyStringConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(string);
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JToken token = JToken.Load(reader);
            // Reverse the string just for fun
            return new string(token.ToString().Reverse().ToArray());
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
    

    Output:

    Name: elppA
    Id: 4b7e9f9f-7a30-4f79-8e47-8b50ea26ddac
    Size: 5
    Quality: 2
    
    0 讨论(0)
提交回复
热议问题