简体   繁体   English

如果名称为大写字母,Newtonsoft JsonConvert.SerializeObject会忽略JsonProperty

[英]Newtonsoft JsonConvert.SerializeObject ignoring JsonProperty if name is uppercase

I want to be able to use the CamelCasePropertyNameContractResolver but override it for specific property names. 我希望能够使用CamelCasePropertyNameContractResolver但将其替换为特定的属性名称。 For this, I use the JsonProperty attribute. 为此,我使用了JsonProperty属性。 This works fine except when the name that I choose is fully uppercase. 除非我选择的名称全为大写,否则此方法工作正常。 Any ideas what's wrong or how to get around it? 任何想法出什么问题或如何解决?

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. 在下面的示例中,当我不使用CamelCasePropertyNameContractResolver时, Bar被序列化为"BAR" ,但是当我使用解析器时, Bar被序列化为"bar" Foo and CamelCaseProperty are serialized correctly in both scenarios. 在两种情况下, FooCamelCaseProperty均已正确序列化。

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; }
    }
}

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 : 您看到它的原因CamelCasePropertyNamesContractResolver是有意设计的,以覆盖字典键的大小写并显式设置属性名称 ,如从参考源中可以看到的:

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. 如果您不希望这样做,则可以使用多个选项来防止在不创建自己的自定义合同解析器类型的情况下使用显式名称。

Firstly , you could serialize using a DefaultContractResolver with NamingStrategy = new CamelCaseNamingStrategy() : 首先 ,您可以使用DefaultContractResolver进行序列化,并带有NamingStrategy = new CamelCaseNamingStrategy()

var settings = new JsonSerializerSettings 
{ 
    ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() }
};
var output2 = JsonConvert.SerializeObject(foo, settings);

This leaves CamelCaseNamingStrategy.OverrideSpecifiedNames at its default value of false . 这将CamelCaseNamingStrategy.OverrideSpecifiedNames为其默认值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: 其次 ,如果您无权访问框架的合同解析器,则可以在特定属性上设置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; }
}

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(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; }
}

Notes: 笔记:

  • While it is also possible to modify the NamingStrategy of an instance of CamelCasePropertyNamesContractResolver , 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 of CamelCasePropertyNamesContractResolver . 尽管也可以修改CamelCasePropertyNamesContractResolver实例的NamingStrategy ,但是由于后者在每种类型的所有实例之间全局共享合同信息 ,如果您的应用程序尝试使用CamelCasePropertyNamesContractResolver多个实例,则可能导致意外的副作用。 No such problem exists with DefaultContractResolver , 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. 使用DefaultContractResolver或对其进行子类化时,您可能希望缓存合同解析器以获得最佳性能,因为它不会在每种类型的所有实例之间全局共享合同信息。

  • 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的驼峰式案例解析器旨在重写指定的名称,这可能是出于历史原因。

  • Naming strategies were first introduced in Json.NET 9.0.1 so this answer works only for that version and later. 命名策略最初是在Json.NET 9.0.1中引入的,因此此答案仅适用于该版本及更高版本。

JsonProperty Attribute is not honoured when you use a ContractResolver. 使用ContractResolver时,不支持JsonProperty属性。

What you can do to solve this issue is override the ContractResolver: 您可以解决此问题的方法是重写ContractResolver:

public class MyResolver : CamelCasePropertyNamesContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        if(member.GetCustomAttribute<JsonPropertyAttribute>() is JsonPropertyAttribute jsonProperty)
        {
            property.PropertyName = jsonProperty.PropertyName;
        }

        return property;
    }
}

And use your Resolver: 并使用您的解析器:

var output2 = JsonConvert.SerializeObject(foo, new JsonSerializerSettings { ContractResolver = new MyResolver() });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 NewtonSoft JsonConvert.SerializeObject中的MaxJsonLength错误 - MaxJsonLength error in NewtonSoft JsonConvert.SerializeObject JsonConvert.SerializeObject添加默认结果名称 - JsonConvert.SerializeObject adds default Result name NewtonSoft JsonConvert.SerializeObject, \" 在序列化 DateTime 后添加 - NewtonSoft JsonConvert.SerializeObject, \" added after serializing DateTime Newtonsoft.Json C# :: 格式化 JsonConvert.SerializeObject - Newtonsoft.Json C# :: Formatting JsonConvert.SerializeObject Newtonsoft.Json.JsonReaderException:在 JsonConvert.SerializeObject 之后解析 JsonConvert.DeserializeObject 时遇到意外字符 - Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing on JsonConvert.DeserializeObject after JsonConvert.SerializeObject JsonConvert.SerializeObject转义反斜杠 - JsonConvert.SerializeObject escaping backslash 为什么我不能在wcf服务中使用Newtonsoft.Json JsonConvert.SerializeObject? - Why I can't use Newtonsoft.Json JsonConvert.SerializeObject in wcf service? NewtonSoft JsonConvert.SerializeObject 确实将零序列化为负零( 0 序列化为 -0.0 ) - NewtonSoft JsonConvert.SerializeObject does serialize zero to negative zero ( 0 serialized like as -0.0 ) JsonConvert.SerializeObject中的默认双值处理 - default double value handling in JsonConvert.SerializeObject JsonConvert.SerializeObject()导致JSON格式错误 - JsonConvert.SerializeObject() causing JSON to be malformed
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM