序列化词典时保留外壳

zaf*_*s.m 80 c# json.net

我有一个Web Api项目配置如下:

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
Run Code Online (Sandbox Code Playgroud)

但是,我希望字典键的外壳保持不变.是否有任何属性Newtonsoft.Json我可以使用一个类来表示我希望在序列化期间套管保持不变?

public class SomeViewModel
{
    public Dictionary<string, string> Data { get; set; }    
}
Run Code Online (Sandbox Code Playgroud)

Bri*_*ers 122

没有属性可以执行此操作,但您可以通过自定义解析程序来执行此操作.

我看到你已经在使用了CamelCasePropertyNamesContractResolver.如果从中派生新的解析程序类并重写该CreateDictionaryContract()方法,则可以提供DictionaryKeyResolver不更改键名称的替换函数.

以下是您需要的代码:

class CamelCaseExceptDictionaryKeysResolver : CamelCasePropertyNamesContractResolver
{
    protected override JsonDictionaryContract CreateDictionaryContract(Type objectType)
    {
        JsonDictionaryContract contract = base.CreateDictionaryContract(objectType);

        contract.DictionaryKeyResolver = propertyName => propertyName;

        return contract;
    }
}
Run Code Online (Sandbox Code Playgroud)

演示:

class Program
{
    static void Main(string[] args)
    {
        Foo foo = new Foo
        {
            AnIntegerProperty = 42,
            HTMLString = "<html></html>",
            Dictionary = new Dictionary<string, string>
            {
                { "WHIZbang", "1" },
                { "FOO", "2" },
                { "Bar", "3" },
            }
        };

        JsonSerializerSettings settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCaseExceptDictionaryKeysResolver(),
            Formatting = Formatting.Indented
        };

        string json = JsonConvert.SerializeObject(foo, settings);
        Console.WriteLine(json);
    }
}

class Foo
{
    public int AnIntegerProperty { get; set; }
    public string HTMLString { get; set; }
    public Dictionary<string, string> Dictionary { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这是上面的输出.请注意,所有类属性名称都是驼峰式的,但字典键保留了原始的外壳.

{
  "anIntegerProperty": 42,
  "htmlString": "<html></html>",
  "dictionary": {
    "WHIZbang": "1",
    "FOO": "2",
    "Bar": "3"
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 仅供参考,PropertyNameResolver 现在已过时。似乎 `contract.DictionaryKeyResolver = key =&gt; key;` 工作得很好。 (2认同)

dbc*_*dbc 59

Json.NET 9.0.1引入了NamingStrategy类层次结构来处理这类问题.它将属性名称的算法重新映射的逻辑从合同解析器提取到单独的轻量级类,该类允许控制是否重新映射字典键,显式指定的属性名称扩展数据名称(在10.0.1中).

通过使用DefaultContractResolver和设置NamingStrategy实例,CamelCaseNamingStrategy您可以通过设置以下内容来生成带有驼峰属性名称和未修改字典键的JSON JsonSerializerSettings.ContractResolver:

var resolver = new DefaultContractResolver
{
    NamingStrategy = new CamelCaseNamingStrategy
    {
        ProcessDictionaryKeys = false,
        OverrideSpecifiedNames = true
    }
};
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = resolver;
Run Code Online (Sandbox Code Playgroud)

笔记:


Dmi*_*riy 11

这是一个非常好的答案.但为什么不覆盖ResolveDictionaryKey

class CamelCaseExceptDictionaryResolver : CamelCasePropertyNamesContractResolver
    {
        #region Overrides of DefaultContractResolver

        protected override string ResolveDictionaryKey(string dictionaryKey)
        {
            return dictionaryKey;
        }

        #endregion
    }
Run Code Online (Sandbox Code Playgroud)