本文主要介绍.NET(C#)中,使用Newtonsoft.JSON的自定义转换器JsonConverter,处理不同的JSON数据输入,能够实现对老数据的兼容。

1、JSON实体类

class Animal
{
    public string Name { get; set; }
    public int Age { get; set; }
}
class BaseObj
{
    public Animal Animal { get; set; }
}
class People : BaseObj
{
    public DateTime StudentTime { get; set; }
}
class Dog : BaseObj
{
    public DateTime EatTime { get; set; }
}

2、自定义JsonConverter(转换器)

1)自定义JsonConverter

class ObjConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(BaseObj).IsAssignableFrom(objectType);
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject obj = JObject.Load(reader);
        string type = (string)obj["$type"];
        BaseObj baseObj;
        if (type.Contains(nameof(People)))
        {
            baseObj = new People();
        }
        else
        {
            baseObj = new Dog();
        }
        serializer.Populate(obj.CreateReader(), baseObj);
        if (baseObj.Animal == null)
        {
            baseObj.Animal = new Animal
            {
                Name = (string)obj["ObjName"],
                Age = (int)obj["ObjAge"]
            };
        }
        return baseObj;
    }
    public override bool CanWrite => false;
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

2)反序列化

var settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Objects,
    Converters = new List { new ObjConverter() }
};
var baseObj = JsonConvert.DeserializeObject(json, settings);

3) 完整代码

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication
{
    class Program
    {
        static ReaderWriterLock rwl = new ReaderWriterLock();
        // 定义ReaderWriterLock对象。
        static int resource = 0;
        const int numThreads = 8;
        static bool running = true;
        static int readerTimeouts = 0;
        static int writerTimeouts = 0;
        static int reads = 0;
        static int writes = 0;
        public static void Main()
        {
            var settings = new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Objects,
                Converters = new List { new ObjConverter() }
            };
            var setting = new Newtonsoft.Json.JsonSerializerSettings
            {
                TypeNameAssemblyFormatHandling = Newtonsoft.Json.TypeNameAssemblyFormatHandling.Simple,
                TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Objects,
            };
            string json = JsonConvert.SerializeObject(new Dog { Animal = new Animal { Age = 1, Name = "dog" }, EatTime = DateTime.Now }, setting);
            Console.WriteLine("json = " + json);
            //json = {"$type":"ConsoleApplication.Dog, ConsoleApp3","EatTime":"2022-02-25T11:0
            //4:07.6480015 + 08:00","Animal":{"$type":"ConsoleApplication.Animal, ConsoleApp3","
            //Name":"dog","Age":1}}
            var baseObj = JsonConvert.DeserializeObject(json, settings);
            Console.ReadKey();
        }
    }
    class Animal
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
    class BaseObj
    {
        public Animal Animal { get; set; }
    }
    class People : BaseObj
    {
        public DateTime StudentTime { get; set; }
    }
    class Dog : BaseObj
    {
        public DateTime EatTime { get; set; }
    }
    class ObjConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(BaseObj).IsAssignableFrom(objectType);
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JObject obj = JObject.Load(reader);
            string type = (string)obj["$type"];
            BaseObj baseObj;
            if (type.Contains(nameof(People)))
            {
                baseObj = new People();
            }
            else
            {
                baseObj = new Dog();
            }
            serializer.Populate(obj.CreateReader(), baseObj);
            if (baseObj.Animal == null)
            {
                baseObj.Animal = new Animal
                {
                    Name = (string)obj["ObjName"],
                    Age = (int)obj["ObjAge"]
                };
            }
            return baseObj;
        }
        public override bool CanWrite => false;
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
}

推荐文档