【问题标题】:Extending the DefaultContractResolver to convert ExpandoObject sub properties to PascalCase扩展 DefaultContractResolver 以将 ExpandoObject 子属性转换为 PascalCase
【发布时间】:2017-05-03 08:27:55
【问题描述】:

我正在尝试编写一个自定义合同解析器,它在 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?

【问题讨论】:

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


    【解决方案1】:

    ExpandoObject 没有通过反射进行序列化,因此修改 CreateProperty 将不起作用。相反,它被序列化为IDictionary<string, object>。因此,您可以利用 Json.NET 9.0.1 中的新 NamingStrategy 类型为 PascalCase only 字典键创建自定义命名策略,仅此而已。 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"
      }
    }
    

    【讨论】:

    • 您的自定义 NamingStrategy 类可以继承自 NamingStrategy 而不是 DefaultNamingStrategy,这种方法仍然有效
    猜你喜欢
    • 1970-01-01
    • 2021-03-05
    • 1970-01-01
    • 2015-08-11
    • 1970-01-01
    • 1970-01-01
    • 2019-07-06
    • 1970-01-01
    • 2022-08-21
    相关资源
    最近更新 更多