C# Newtonsoft.Json 反序列化派生类数据丢失问题

代码:

cs 复制代码
internal class Program
    {
        static void Main(string[] args)
        {
            string path = $"{Environment.CurrentDirectory}\\test.json";

            List<TestBase> list = new List<TestBase>();
            list.Add(new Test1() { index1 = 1, Name = "a1" });
            list.Add(new Test2() { index2 = 2, Name = "a2" });
            list.Add(new Test3() { index3 = 3, Name = "a3" });

            string json = JsonConvert.SerializeObject(list);
            File.WriteAllText(path, json);

            string readJson = File.ReadAllText(path);
            var list2 = JsonConvert.DeserializeObject<List<TestBase>>(json);
            Console.WriteLine("现在每个 Test 类的 Index 已经丢失");

            Console.ReadKey();
        }
    }

    public class TestBase
    {
        public string Name { get; set; }
    }

    public class Test1 : TestBase 
    {
        public int index1 { get; set; }
    }

    public class Test2 : TestBase
    {
        public int index2 { get; set; }
    }

    public class Test3 : TestBase
    {
        public int index3 { get; set; }
    }

在上面的代码中,将 Json 反序列化后,对于的 Index 值都会丢失,因为这种写法,父类的数据在反序列化时,没有赋值导致的

解决方式:

在序列化和反序列化时,加上下面的代码

序列化:

cs 复制代码
var settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
};
string json = JsonConvert.SerializeObject(list, settings);

反序列化:

cs 复制代码
var settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
};
var list2 = JsonConvert.DeserializeObject<List<TestBase>>(readJson, settings);

案例1:

cs 复制代码
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.IO;

internal class Program
{
    static void Main(string[] args)
    {
        string path = $"{Environment.CurrentDirectory}\\test.json";

        // 初始化列表
        List<TestBase> list = new List<TestBase>
        {
            new Test1() { index1 = 1, Name = "a1" },
            new Test2() { index2 = 2, Name = "a2" },
            new Test3() { index3 = 3, Name = "a3" }
        };

        // 序列化时包含类型信息
        var settings = new JsonSerializerSettings
        {
            TypeNameHandling = TypeNameHandling.Auto // 自动添加 $type 字段
        };

        string json = JsonConvert.SerializeObject(list, settings);
        File.WriteAllText(path, json);

        // 读取 JSON 并反序列化
        string readJson = File.ReadAllText(path);
        var list2 = JsonConvert.DeserializeObject<List<TestBase>>(readJson, settings);

        // 验证反序列化后的数据
        foreach (var item in list2)
        {
            if (item is Test1 test1)
                Console.WriteLine($"Test1: {test1.Name}, index1 = {test1.index1}");
            else if (item is Test2 test2)
                Console.WriteLine($"Test2: {test2.Name}, index2 = {test2.index2}");
            else if (item is Test3 test3)
                Console.WriteLine($"Test3: {test3.Name}, index3 = {test3.index3}");
        }

        Console.ReadKey();
    }
}

public class TestBase
{
    public string Name { get; set; }
}

public class Test1 : TestBase
{
    public int index1 { get; set; }
}

public class Test2 : TestBase
{
    public int index2 { get; set; }
}

public class Test3 : TestBase
{
    public int index3 { get; set; }
}

案例2:

cs 复制代码
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;

namespace 反序列化
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Data data = new Data();

            Test1 test1 = new Test1();
            test1.Name = "test1";
            test1.Text = "a";

            Test2 test2 = new Test2();
            test2.Name = "test2";
            test2.Text = "b";
            test2.Value = 1;

            string key = "key";
            if (!data.myDic.TryGetValue(key, out var list))
            {
                list = new List<TestBase>();
                data.myDic[key] = list;
            }
            list.Add(test1);
            list.Add(test2);

            string path = $"{Environment.CurrentDirectory}\\test.json";

            var settings = new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Auto
            };

            string json = JsonConvert.SerializeObject(list, settings);
            File.WriteAllText(path, json);

            string readJson = File.ReadAllText(path);
            var list2 = JsonConvert.DeserializeObject<List<TestBase>>(readJson, settings);
            if(list.Count == 2)
            {
                if (list[0] is Test1 _test1)
                {
                    Console.WriteLine("Test1.Name={0}, Test1.Text={1}", _test1.Name, _test1.Text);
                }
                if (list[1] is Test2 _test2)
                {
                    Console.WriteLine("Test2.Name={0}, Test2.Text={1}, Test2.Value={2}", _test2.Name, _test2.Text, _test2.Value);
                }
            }

            Console.ReadKey();
        }
    }
}


public class TestBase
{
    public string Name { get; set; }
}

public class Test1 : TestBase
{
    public string Text { get; set; }
}

public class Test2 : TestBase
{
    public int Value { get; set; }
    public string Text { get; set; }
}

public class Data
{
    public Dictionary<string,List<TestBase>> myDic = new Dictionary<string,List<TestBase>>();
}

运行:

end

相关推荐
典典分享指南10 小时前
一品牌多产品线的 GEO 内容矩阵:从策略到落地
java·c#·bash·symfony
今夜有雨.10 小时前
C# 学习文档(零基础入门)
开发语言·学习·c#
软件黑马王子11 小时前
14.事件中心:主要作用和原理
开发语言·前端框架·c#
海盗123416 小时前
微软技术周报 2026-08-31~09-07:GPT-6 Astra 登陆 Foundry、M365 全球认证故障复盘、C# 15 封闭层级
gpt·microsoft·c#
reasonsummer17 小时前
【办公类-115-01】20260906育儿知识(家园小报)批量制作(2026年9月-2027年6月)
开发语言·数据库·c#
软件黑马王子18 小时前
13.缓存池优化:对象上限配置
开发语言·前端框架·c#
唐青枫18 小时前
C#.NET StructureMap 从依赖注入到项目实战
c#·.net
fujisheng66118 小时前
FUI 编译期装配实践:从反射注册到 Source Generator
c#·unity3d
牛油果子哥q18 小时前
C++对接LLM完整工程:异步HTTP请求、JSON解析、超时容错、重连兜底
c++·http·json
智码看视界18 小时前
.NET 10 推理大模型TensorSharp 3.3.0 部署实测:纯.NET推理引擎反超llama.cpp 1.5倍,DFlash2提速62%
c#·.net·llama.cpp·.net 10·tensorsharp·本地大模型推理·开源推理引擎