簡體   English   中英

如果名稱為大寫字母,Newtonsoft JsonConvert.SerializeObject會忽略JsonProperty

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

我希望能夠使用CamelCasePropertyNameContractResolver但將其替換為特定的屬性名稱。 為此,我使用了JsonProperty屬性。 除非我選擇的名稱全為大寫,否則此方法工作正常。 任何想法出什么問題或如何解決?

在下面的示例中,當我不使用CamelCasePropertyNameContractResolver時, Bar被序列化為"BAR" ,但是當我使用解析器時, Bar被序列化為"bar" 在兩種情況下, 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; }
    }
}

您看到它的原因CamelCasePropertyNamesContractResolver是有意設計的,以覆蓋字典鍵的大小寫並顯式設置屬性名稱 ,如從參考源中可以看到的:

public CamelCasePropertyNamesContractResolver()
{
    NamingStrategy = new CamelCaseNamingStrategy
    {
        ProcessDictionaryKeys = true,
        OverrideSpecifiedNames = true
    };
}

如果您不希望這樣做,則可以使用多個選項來防止在不創建自己的自定義合同解析器類型的情況下使用顯式名稱。

首先 ,您可以使用DefaultContractResolver進行序列化,並帶有NamingStrategy = new CamelCaseNamingStrategy()

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<JsonPropertyAttribute>() is JsonPropertyAttribute jsonProperty)
        {
            property.PropertyName = jsonProperty.PropertyName;
        }

        return property;
    }
}

並使用您的解析器:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM