C# 在序列化词典时保留大小写

C# 在序列化词典时保留大小写,c#,json.net,C#,Json.net,我有一个Web Api项目的配置如下: config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 但是,我希望字典键保持不变。Newtonsoft.Json中是否有任何属性可用于类,以表示我希望在序列化过程中保持大小写不变 public class SomeViewModel { public Dictionary

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

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
但是,我希望字典键保持不变。
Newtonsoft.Json
中是否有任何属性可用于类,以表示我希望在序列化过程中保持大小写不变

public class SomeViewModel
{
    public Dictionary<string, string> Data { get; set; }    
}
公共类SomeViewModel
{
公共字典数据{get;set;}
}

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

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

以下是您需要的代码:

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

        contract.DictionaryKeyResolver = propertyName => propertyName;

        return contract;
    }
}
演示:

类程序
{
静态void Main(字符串[]参数)
{
Foo Foo=新Foo
{
整数属性=42,
HTMLString=“”,
字典=新字典
{
{“惠茨邦”,“1”},
{“FOO”,“2”},
{“Bar”,“3”},
}
};
JsonSerializerSettings设置=新的JsonSerializerSettings
{
ContractResolver=新CamelCaseExceptDictionaryKeysResolver(),
格式化=格式化。缩进
};
字符串json=JsonConvert.SerializeObject(foo,设置);
Console.WriteLine(json);
}
}
福班
{
公共整数整数属性{get;set;}
公共字符串HTMLString{get;set;}
公共字典{get;set;}
}
这是上面的输出。请注意,所有类属性名称都是驼峰大小写的,但字典键保留了其原始大小写

{
  "anIntegerProperty": 42,
  "htmlString": "<html></html>",
  "dictionary": {
    "WHIZbang": "1",
    "FOO": "2",
    "Bar": "3"
  }
}
{
“集成财产”:42,
“htmlString”:“,
“字典”:{
“惠茨邦”:“1”,
“FOO”:“2”,
“酒吧”:“3”
}
}

所选答案非常完美,但我想当我键入此内容时,契约解析程序必须更改为类似的内容,因为DictionaryKeyResolver不再存在:)


这是一个非常好的回答。但是为什么不直接覆盖
ResolveDictionaryKey

class CamelCaseExceptDictionaryResolver : CamelCasePropertyNamesContractResolver
    {
        #region Overrides of DefaultContractResolver

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

        #endregion
    }
引入类层次结构来处理此类问题。它将属性名称的算法重新映射逻辑从契约解析器提取到一个单独的轻量级类,该类允许控制是否重新映射和(in)

通过使用并设置的实例,您可以通过在以下中设置来生成带有驼峰大小写属性名和未修改字典键的JSON:

注:

  • 的当前实现还指定具有显式指定的属性名称(例如,已设置的属性名称)的.Net成员应重新映射其名称:

    public CamelCasePropertyNamesContractResolver()
    {
        NamingStrategy = new CamelCaseNamingStrategy
        {
            ProcessDictionaryKeys = true,
            OverrideSpecifiedNames = true
        };
    }
    
    上面的
    解析器
    保留此行为。如果不希望这样,请设置
    OverrideSpecifiedNames=false

  • Json.NET有几种内置的命名策略,包括:

  • 。一种骆驼案例命名策略,包含以前嵌入在
    CamelCasePropertyNamesContractResolver
    中的名称重新映射逻辑
  • 。命名策略
  • 。默认命名策略。属性名和字典键保持不变 或者,您可以通过继承抽象基类
    NamingStrategy
    来创建自己的

  • 虽然也可以修改的实例的
    NamingStrategy
    ,但由于后者,如果应用程序尝试使用多个
    CamelCasePropertyNamesContractResolver
    实例,这可能会导致意外的副作用。
    DefaultContractResolver
    不存在这样的问题,因此在需要定制外壳逻辑时使用它更安全


您尝试过默认解析器吗?@Matthew没有,我没有;你能用一个例子解释一下代码是什么样子的吗?请注意,我仍然希望对所有web api请求使用驼峰大小写序列化,我只希望对类(或任何字典键)进行自定义序列化。仅供参考,PropertyNameResolver现在已过时。似乎
contract.DictionaryKeyResolver=key=>key工作得很好。这仍然与匿名类型非常相关,特别是当我们确实希望大部分结构使用驼峰式大小写,但不希望字典中的键被驼峰式化时。绝对同意Chris的观点。我不得不在JavaScript中经历重重困难,因为我无法避免字典被套住。事实证明,一行代码就可以解决这个问题(并使我的JavaScript更简单)@布莱恩罗杰斯的作品很棒!但是,您知道我是否可以仅在Dictionary属性具有某些自定义属性的情况下使用Dictionary KeyResolver来调节吗?@Mugen不是我想的那样。我建议把这个问题作为一个新问题提出来。如果您需要提供上下文,可以链接回这个问题。非常简洁。Thx用于共享。实际上情况正好相反。您必须使用旧版本的Json.Net<代码>字典KeyResolver
已添加,并且
PropertyNameResolver
被标记为已过时。此解决方案不适用于类似
公共字典值{get;set;}
的属性。对于内部字典键,它仍然使用camelCase。@hikalkan-虽然我无法重现您的确切问题,但在使用多个
CamelCasePropertyNamesContractResolver
实例时,我发现了一个问题。基本上,第一种策略将影响第二种策略生成的合同。这可能就是你所看到的。请尝试新的建议,让我知道if是否解决了您的问题。是否有灵活的
NamingStrategy
,以便它能够同时解析camel case和pascal case?@dbc在初始代码示例中,什么是
co
class CamelCaseExceptDictionaryResolver : CamelCasePropertyNamesContractResolver
    {
        #region Overrides of DefaultContractResolver

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

        #endregion
    }
var resolver = new DefaultContractResolver
{
    NamingStrategy = new CamelCaseNamingStrategy
    {
        ProcessDictionaryKeys = false,
        OverrideSpecifiedNames = true
    }
};
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = resolver;
public CamelCasePropertyNamesContractResolver()
{
    NamingStrategy = new CamelCaseNamingStrategy
    {
        ProcessDictionaryKeys = true,
        OverrideSpecifiedNames = true
    };
}