Newtonsoft JsonConvert.SerializeObject如果名称为大写,则忽略JsonProperty
我希望能够使用CamelCasePropertyNameContractResolver
,但要为特定的属性名称覆盖它.为此,我使用JsonProperty
属性.除非我选择的名称全为大写,否则此方法工作正常.有任何想法出什么问题或如何解决吗?
I want to be able to use the CamelCasePropertyNameContractResolver
but override it for specific property names. For this, I use the JsonProperty
attribute. This works fine except when the name that I choose is fully uppercase. Any ideas what's wrong or how to get around it?
在下面的示例中,当我不使用CamelCasePropertyNameContractResolver时,Bar
被序列化为"BAR"
,但是当我使用解析器时,被序列化为"bar"
.在两种情况下,Foo
和CamelCaseProperty
均已正确序列化.
In the example below, Bar
is serialized to "BAR"
when I don't use the CamelCasePropertyNameContractResolver, but is serialized to "bar"
when I do use the resolver. Foo
and CamelCaseProperty
are serialized correctly in both scenarios.
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
旨在覆盖明确设置属性名称,如
The reason you are seeing this is that CamelCasePropertyNamesContractResolver
is intentionally designed to override the casing of dictionary keys and explicitly set property names, as can be see from the reference source:
public CamelCasePropertyNamesContractResolver()
{
NamingStrategy = new CamelCaseNamingStrategy
{
ProcessDictionaryKeys = true,
OverrideSpecifiedNames = true
};
}
如果您不希望这样做,则可以使用多个选项来防止在不创建自己的自定义合同解析器类型的情况下使用显式名称进行大小写.
If you don't want that, you have several options to prevent casing of explicit names without creating your own custom contract resolver type.
首先,您可以使用 NamingStrategy = new CamelCaseNamingStrategy()
:
Firstly, you could serialize using a DefaultContractResolver
with NamingStrategy = new CamelCaseNamingStrategy()
:
var settings = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() }
};
var output2 = JsonConvert.SerializeObject(foo, settings);
这会将 CamelCaseNamingStrategy.OverrideSpecifiedNames
保留为默认值
This leaves CamelCaseNamingStrategy.OverrideSpecifiedNames
at its default value of false
.
Secondly, if you don't have access to the contract resolver of your framework, you could set JsonPropertyAttribute.NamingStrategyType = typeof(DefaultNamingStrategy)
on specific properties, like so:
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; }
}
第三次,如果您想让整个对象忽略当前合同解析器的命名策略,则可以应用
Thirdly, if you want your entire object to ignore the naming strategy of the current contract resolver, you can apply [JsonObject(NamingStrategyType = typeof(TNamingStrategy))]
to your object:
[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
实例,则可能导致意外的副作用.DefaultContractResolver
不存在这样的问题,因此在需要对大小写逻辑进行任何自定义时,使用起来更安全.
While it is also possible to modify the
NamingStrategy
of an instance ofCamelCasePropertyNamesContractResolver
, since the latter shares contract information globally across all instances of each type, this can lead to unexpected side-effects if your application tries to use multiple instances ofCamelCasePropertyNamesContractResolver
. No such problem exists withDefaultContractResolver
, so it is safer to use when any customization of casing logic is required.
使用或子类化DefaultContractResolver
时,您可能想要缓存合同解析器,以获得最佳性能,因为它不会在每种类型的所有实例之间全局共享合同信息.
When using or subclassing DefaultContractResolver
, you may want to cache the contract resolver for best performance, since it does not share contract information globally across all instances of each type.
我不知道为什么Json.NET的驼峰式案例解析器旨在重写指定的名称,这可能是出于历史原因.
I don't know why Json.NET's camel case resolver is designed to override specified names, it may be for historical reasons.
命名策略最初是在 Json.NET 9.0中引入的. 1 ,因此此答案仅适用于该版本及更高版本.
Naming strategies were first introduced in Json.NET 9.0.1 so this answer works only for that version and later.