You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Json.NET仅序列化/反序列化类型的指定私有字段?

仅序列化指定私有字段的Json.NET实现方案

问题背景

需要对MyClass类型仅序列化/反序列化指定的私有字段,忽略其他所有公开/私有字段及属性。当前采用Dictionary<string, object>作为中间类型的方案,序列化正常,但反序列化时因字典中object值类型不匹配、反射逻辑错误导致失败。

解决方案

方案一:自定义JsonConverter(推荐)

直接通过自定义JsonConverter控制序列化和反序列化过程,无需中间字典,更贴合Json.NET的设计思路。

实现自定义转换器

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Reflection;
using System.Collections.Generic;

public class MyClassConverter : JsonConverter<MyClass>
{
    // 明确要序列化的私有字段列表
    private readonly HashSet<string> _targetFields = new HashSet<string>
    {
        nameof(MyClass.SomeParameters),
        nameof(MyClass.notifications),
        nameof(MyClass.someKey),
        nameof(MyClass.someNumber),
        nameof(MyClass.aChar)
    };

    public override void WriteJson(JsonWriter writer, MyClass? value, JsonSerializer serializer)
    {
        if (value == null)
        {
            writer.WriteNull();
            return;
        }

        writer.WriteStartObject();

        // 反射获取目标私有字段并序列化
        foreach (var fieldName in _targetFields)
        {
            var field = typeof(MyClass).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
            if (field != null)
            {
                var fieldValue = field.GetValue(value);
                writer.WritePropertyName(fieldName);
                serializer.Serialize(writer, fieldValue);
            }
        }

        writer.WriteEndObject();
    }

    public override MyClass? ReadJson(JsonReader reader, Type objectType, MyClass? existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;

        var instance = existingValue ?? new MyClass();
        var jsonObj = JObject.Load(reader);

        // 反射设置目标私有字段
        foreach (var fieldName in _targetFields)
        {
            var field = typeof(MyClass).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
            if (field != null && jsonObj.TryGetValue(fieldName, StringComparison.OrdinalIgnoreCase, out var token))
            {
                var fieldValue = token.ToObject(field.FieldType, serializer);
                field.SetValue(instance, fieldValue);
            }
        }

        return instance;
    }
}

使用方式

序列化/反序列化时指定转换器即可:

// 序列化示例
var myObj = new MyClass(
    new Dictionary<string, Parameters> { { "name", new Parameters("hello", "There") } },
    new NotificationList(),
    "some key",
    101,
    'z'
);
string json = JsonConvert.SerializeObject(myObj, new MyClassConverter());

// 反序列化示例
var deserializedObj = JsonConvert.DeserializeObject<MyClass>(json, new MyClassConverter());

方案二:修复原有Dictionary方案

如果坚持使用中间字典,需要解决两个核心问题:

  1. 反射时错误获取了Dictionary<string,object>的字段,而非MyClass的字段
  2. 反序列化字典时需将object值转换为字段实际类型

修复后的FromDictionary方法

public partial class MyClass
{
    public Dictionary<string, object> ToDictionary() => new()
    {
        { nameof(SomeParameters), SomeParameters},
        { nameof(notifications), notifications },
        { nameof(someKey), someKey },
        { nameof(someNumber), someNumber },
        { nameof(aChar), aChar },
    };
    
    public static MyClass FromDictionary(Dictionary<string, object> settings)
    {
        var instance = new MyClass();
        var myClassType = typeof(MyClass);

        foreach (var kvp in settings)
        {
            // 正确获取MyClass的私有字段
            FieldInfo? fieldInfo = myClassType.GetField(kvp.Key, BindingFlags.NonPublic | BindingFlags.Instance);
            if (fieldInfo == null) continue;

            // 将字典中的object值转换为字段实际类型
            var fieldValue = JsonConvert.DeserializeObject(
                JsonConvert.SerializeObject(kvp.Value), 
                fieldInfo.FieldType
            );
            fieldInfo.SetValue(instance, fieldValue);
        }           
        
        return instance;
    }
}

反序列化字典的正确流程

// 序列化字典
string json = JsonConvert.SerializeObject(myObj.ToDictionary());
// 反序列化并重建实例
var settingsDict = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
var restoredObj = MyClass.FromDictionary(settingsDict);

关键说明

  • 自定义Converter方案无需额外中间类型,直接控制序列化逻辑,类型安全且性能更优
  • 修复Dictionary方案时,核心是正确反射目标类的字段和将object值转换为字段实际类型

内容的提问来源于stack exchange,提问作者livan3li

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 01:45:57