我正在尝试编写一个自定义合约解析程序,它在Newtonsoft.Json.Serialization中扩展DefaultContractResolver,目标是将ExpandoObject中的所有属性转换为具有PascalCase属性名称。
我的合同:
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?
答案 0 :(得分:2)
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"
}
}