c# - 扩展 DefaultContractResolver 以将 ExpandoObject 子属性转换为 PascalCase

标签 c# asp.net-mvc serialization json.net expandoobject

我正在尝试编写一个自定义契约(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/

相关文章:

c# - Delphi 扩展到 C#

c# - Active Directory 中的过滤器更改通知 : Create, 删除、取消删除

c# - Configuration.GetSection ("basicHttpBinding") 没有从 app.config 文件中读取该部分

c# - 如何计算 LINQ(到数据集)中数据表列的总和?

c# - 在 ASP.net 中运行时调用存储过程

scala - Scala/Akka 中的序列化

c# - 使用 Json.NET 序列化 : how to require a property not being null?

asp.net-mvc - 模型仅绑定(bind)所选项目的列表

c# - .net mvc - 如何使类方法参数 (IQueryable) 可以为空

android - DateTime 是可序列化的,但序列化不正确?