如何用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
相关产品推荐
相关产品推荐

