如何让顶级类的Json.NET命名策略属性作用于嵌套类?
问题:让顶级类的Json.NET命名策略自动作用于嵌套类?
我有如下代码,在顶级类Foo上添加了[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]属性,但序列化时只有Foo的成员遵循驼峰命名,嵌套类NestedFoo的成员NestedBar没有被序列化为nestedBar:
internal class Program { [JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))] public class Foo { public string Bar; public NestedFoo NestedFoo { get; set; } } public class NestedFoo { public string NestedBar; } static void Main(string[] args) { Foo c = new(); c.NestedFoo = new(); c.Bar = "Bar"; c.NestedFoo.NestedBar = "NestedBar "; string output = JsonConvert.SerializeObject(c, Formatting.Indented); Console.WriteLine(output); } }
序列化输出:
{ "bar": "Bar", "nestedFoo": { "NestedBar": "NestedBar " } }
已知两种解决方案,但希望仅通过修改顶级类的属性实现需求:
- 为每个嵌套类添加
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]属性; - 为
JsonConvert.SerializeObject方法传入全局命名策略。
请问是否存在方法,让顶级类的命名策略属性同时作用于自身及所有嵌套属性?
解决方案
Json.NET原生不支持自动将顶级类的NamingStrategyType传递给嵌套类,要实现仅通过顶级类属性达到需求,需要自定义ContractResolver并配合类属性使用:
1. 自定义ContractResolver
创建一个继承自DefaultContractResolver的解析器,重写CreateContract方法,让嵌套类继承父对象的命名策略:
public class InheritedNamingContractResolver : DefaultContractResolver { protected override JsonContract CreateContract(Type objectType) { var contract = base.CreateContract(objectType); // 获取当前父对象的JsonObject属性,继承其命名策略 var parentObj = Serializer?.Context?.CurrentObject; if (parentObj != null) { var parentAttr = parentObj.GetType().GetCustomAttribute<JsonObjectAttribute>(); if (parentAttr != null && parentAttr.NamingStrategyType != null) { contract.NamingStrategy = Activator.CreateInstance(parentAttr.NamingStrategyType) as NamingStrategy; } } return contract; } }
2. 在顶级类上指定自定义Resolver和命名策略
修改Foo类的[JsonObject]属性,同时指定自定义ContractResolver和驼峰命名策略:
[JsonObject( ContractResolverType = typeof(InheritedNamingContractResolver), NamingStrategyType = typeof(CamelCaseNamingStrategy) )] public class Foo { public string Bar; public NestedFoo NestedFoo { get; set; } }
3. 序列化效果
此时重新运行代码,输出会符合预期:
{ "bar": "Bar", "nestedFoo": { "nestedBar": "NestedBar " } }
这个方案只需要修改顶级类的属性,不需要改动嵌套类或序列化方法的参数,完全符合需求。
内容的提问来源于stack exchange,提问作者Allan Xu
相关产品推荐
相关产品推荐

