我正在尝试编写一个自定义契约(Contract)解析器,它在 Newtonsoft.Json.Serialization 中扩展 DefaultContractResolver,目标是将 ExpandoObject 中的所有属性转换为具有 PascalCase 属性名称。
我的契约(Contract):
public class Fruit
{
public int Id { get; set; }
public ExpandoObject FruitProperties { get; set; }
}
我正在传递以下数据:
{
"Id": "1234",
"FruitProperties" : {
"colour": "red",
"Taste": "sweet
}
}
}
我期望的结果如下:
{
"Id": "1234",
"FruitProperties" : {
"Colour": "red",
"Taste": "sweet"
}
}
我曾尝试覆盖 DefaultContractResolver 中的 ResolvePropertyName 和 CreateProperty 方法,但没有成功。所有这些都跳过了 expando 对象中的子属性。有谁知道我需要覆盖 DefaultContractResolver 中的什么方法才能将 Expando 中的子属性名称转换为 PascalCase?
最佳答案
ExpandoObject
未通过反射序列化,因此修改 CreateProperty
不会工作。相反,它被序列化为 IDictionary<string, object>
。 .因此,您可以利用新的 NamingStrategy
输入 Json.NET 9.0.1为 PascalCase 仅字典键创建自定义命名策略,别无其他。 NamingStrategy
有一个属性 NamingStrategy.ProcessDictionaryKeys
那,当设置为 true
, 导致 Json.NET 映射字典键名:
public class PascalCaseDictionaryKeyNamingStrategy : DefaultNamingStrategy
{
public PascalCaseDictionaryKeyNamingStrategy() : base() { this.ProcessDictionaryKeys = true; }
public override string GetDictionaryKey(string key)
{
if (ProcessDictionaryKeys && !string.IsNullOrEmpty(key))
{
if (char.ToUpperInvariant(key[0]) != key[0])
{
var builder = new StringBuilder(key);
builder[0] = char.ToUpperInvariant(key[0]);
return builder.ToString();
}
}
return key;
}
}
然后设置为 DefaultContractResolver.NamingStrategy
(或任何 custom subclass of DefaultContractResolver
,如果您愿意):
var resolver = new DefaultContractResolver { NamingStrategy = new PascalCaseDictionaryKeyNamingStrategy() };
var json = JsonConvert.SerializeObject(fruit, Formatting.Indented, new JsonSerializerSettings { ContractResolver = resolver });
Console.WriteLine(json);
哪些输出:
{
"Id": 1234,
"FruitProperties": {
"Colour": "red",
"Taste": "sweet"
}
}
关于c# - 扩展 DefaultContractResolver 以将 ExpandoObject 子属性转换为 PascalCase,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41203072/