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

如何用Json.NET将带JsonProperty路径的扁平C#类序列化为嵌套JSON

使用Json.NET将扁平C#类序列化为嵌套JSON

默认情况下,Json.NET序列化时会直接把JsonProperty特性指定的完整字符串作为JSON键,不会自动拆分点分隔的层级。要实现将扁平类转为嵌套JSON,你可以通过**自定义ContractResolver**处理带点的属性名,完全不需要创建额外子类。

实现自定义ContractResolver

创建继承自DefaultContractResolver的类,重写属性创建逻辑,将带点的属性名拆分为嵌套结构:

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

public class NestedJsonPropertyContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var properties = base.CreateProperties(type, memberSerialization);
        var nestedProperties = new List<JsonProperty>();

        foreach (var property in properties)
        {
            var propertyName = property.PropertyName;
            if (!propertyName.Contains("."))
            {
                nestedProperties.Add(property);
                continue;
            }

            var parts = propertyName.Split('.');
            var parentProperty = CreateNestedProperty(parts, 0, property);
            nestedProperties.Add(parentProperty);
        }

        return nestedProperties;
    }

    private JsonProperty CreateNestedProperty(string[] parts, int index, JsonProperty originalProperty)
    {
        var currentPart = parts[index];
        var isLeaf = index == parts.Length - 1;

        var property = new JsonProperty
        {
            PropertyName = currentPart,
            Readable = true,
            Writable = true
        };

        if (isLeaf)
        {
            property.ValueProvider = originalProperty.ValueProvider;
            property.PropertyType = originalProperty.PropertyType;
            property.Converter = originalProperty.Converter;
            property.NullValueHandling = originalProperty.NullValueHandling;
        }
        else
        {
            var nestedType = typeof(Dictionary<string, object>);
            property.PropertyType = nestedType;
            property.ValueProvider = new NestedValueProvider(parts, index + 1, originalProperty);
        }

        return property;
    }

    private class NestedValueProvider : IValueProvider
    {
        private readonly string[] _parts;
        private readonly int _index;
        private readonly JsonProperty _originalProperty;

        public NestedValueProvider(string[] parts, int index, JsonProperty originalProperty)
        {
            _parts = parts;
            _index = index;
            _originalProperty = originalProperty;
        }

        public object GetValue(object target)
        {
            var value = _originalProperty.ValueProvider.GetValue(target);
            var nestedDict = new Dictionary<string, object>();
            var currentDict = nestedDict;

            for (int i = _index; i < _parts.Length - 1; i++)
            {
                var newDict = new Dictionary<string, object>();
                currentDict[_parts[i]] = newDict;
                currentDict = newDict;
            }

            currentDict[_parts[^1]] = value;
            return nestedDict;
        }

        public void SetValue(object target, object value)
        {
            // 序列化场景无需实现SetValue,反序列化逻辑已自行处理
        }
    }
}

使用示例

序列化时将自定义ContractResolver传入配置即可:

var myInstance = new MyClass();
var settings = new JsonSerializerSettings
{
    ContractResolver = new NestedJsonPropertyContractResolver(),
    Formatting = Formatting.Indented
};

var json = JsonConvert.SerializeObject(myInstance, settings);

执行后得到的JSON结构如下:

{
  "subgroupa": {
    "myotherproperty": 5
  }
}

核心说明

  • 自定义解析器会遍历类属性,自动拆分带点的属性名,构建嵌套JSON结构
  • 叶子节点直接绑定原属性的取值逻辑,非叶子节点通过嵌套字典生成层级
  • 无需修改原有类结构,完全避免额外子类带来的代码开销

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 21:45:32