如果name为大写,则Newtonsoft JsonConvert.SerializeObject忽略JsonProperty
我希望能够使用CamelCasePropertyNameContractResolver
但是为特定的属性名称覆盖它。 为此,我使用JsonProperty
属性。 这工作正常,除非我选择的名称是完全大写。 任何想法有什么问题或如何解决它?
在下面的示例中,当我不使用CamelCasePropertyNameContractResolver时, Bar
被序列化为"BAR"
,但在我使用解析器时序列化为"bar"
。 在两种情况下都可以正确序列化Foo
和CamelCaseProperty
。
using Newtonsoft.Json; using Newtonsoft.Json.Serialization; namespace ConsoleTester { class Program { static void Main(string[] args) { var foo = new FooBar {CamelCaseProperty = "test", Foo = "test", Bar = "test" }; var output = JsonConvert.SerializeObject(foo); // output "CamelCaseProperty", "fOO", "BAR" var output2 = JsonConvert.SerializeObject(foo, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }); // output "camelCaseProperty", "fOO", "bar" } } public class FooBar { public string CamelCaseProperty { get; set; } [JsonProperty("fOO")] public string Foo { get; set; } [JsonProperty("BAR")] public string Bar { get; set; } } }
您看到这个的原因是CamelCasePropertyNamesContractResolver
被有意设计为覆盖字典键的大小并显式设置属性名称 ,从参考源可以看出:
public CamelCasePropertyNamesContractResolver() { NamingStrategy = new CamelCaseNamingStrategy { ProcessDictionaryKeys = true, OverrideSpecifiedNames = true }; }
如果您不想这样做,则可以使用多个选项来防止显式名称的大小写,而无需创建自己的自定义合约解析程序类型。
首先 ,您可以使用带有NamingStrategy = new CamelCaseNamingStrategy()
的DefaultContractResolver
进行序列化:
var settings = new JsonSerializerSettings { ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() } }; var output2 = JsonConvert.SerializeObject(foo, settings);
这使得CamelCaseNamingStrategy.OverrideSpecifiedNames
的默认值为false
。
其次 ,如果您无权访问框架的合约解析程序,则可以在特定属性上设置JsonPropertyAttribute.NamingStrategyType = typeof(DefaultNamingStrategy)
,如下所示:
public class FooBar { public string CamelCaseProperty { get; set; } [JsonProperty("fOO")] public string Foo { get; set; } [JsonProperty("BAR", NamingStrategyType = typeof(DefaultNamingStrategy))] public string Bar { get; set; } }
第三 ,如果您希望整个对象忽略当前合约解析器的命名策略,可以将[JsonObject(NamingStrategyType = typeof(TNamingStrategy))]
应用于您的对象:
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))] public class FooBar { public string CamelCaseProperty { get; set; } [JsonProperty("fOO")] public string Foo { get; set; } [JsonProperty("BAR")] public string Bar { get; set; } }
笔记:
-
虽然也可以修改
CamelCasePropertyNamesContractResolver
实例的NamingStrategy
,因为后者在每种类型的所有实例之间全局共享合同信息 ,如果您的应用程序尝试使用CamelCasePropertyNamesContractResolver
多个实例,这可能会导致意外的副作用。DefaultContractResolver
不存在这样的问题,因此在需要任何自定义套管逻辑时使用它会更安全。 -
使用或
DefaultContractResolver
,您可能希望缓存合同解析程序以获得最佳性能,因为它不会在每种类型的所有实例中全局共享合同信息。 -
我不知道为什么Json.NET的骆驼案例解析器被设计为覆盖指定的名称,这可能是出于历史原因。
-
命名策略最初是在Json.NET 9.0.1中引入的,所以这个答案仅适用于该版本以及之后的版本。
使用ContractResolver时,JsonProperty属性不受尊重。
您可以采取的措施来覆盖ContractResolver:
public class MyResolver : CamelCasePropertyNamesContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var property = base.CreateProperty(member, memberSerialization); if(member.GetCustomAttribute() is JsonPropertyAttribute jsonProperty) { property.PropertyName = jsonProperty.PropertyName; } return property; } }
并使用你的解析器:
var output2 = JsonConvert.SerializeObject(foo, new JsonSerializerSettings { ContractResolver = new MyResolver() });