三:C#對象轉換Json時的一些高級(特殊)設置;


導航目錄:

   Newtonsoft.Json 概述

  一:Newtonsoft.Json 支持序列化與反序列化的.net 對象類型;

    二:C#對象、集合、DataTable與Json內容互轉示例;

  三:C#對象轉換Json時的一些高級(特殊)設置;

 

   前面兩篇分別介紹了C#轉換JSON時一些常規的用法,以前我也是,只用到了前面這些比較常用的方法,沒想到在轉換時還有那么多特殊的設置,

今天這篇內容就來講一下一些特殊的設置,比如,轉換時過濾掉個別屬性、重命名字段名稱、枚舉字段的處理、私有變量的轉換等;

  好了,開始今天的正題:

序列化時忽略特定的屬性字段

需求分析:有時候在前后台或者APP直接進行數據交互的時候,不需要全部的屬性內容,舉個栗子,比如,只想知道用戶的名字叫啥,如果把用戶的年齡、

性別,愛好都返回,中間的傳輸過程就會占用寬帶,而且,其它的字段也不需要,也浪費了轉換的性能。SO,還是前面文章中的對象類,咱們改進下,比

如,現在我們只想要這個用戶的名字叫啥,代碼怎么改呢?

有兩種方式可以實現,方式1:比如你去飯店,告訴老板我要這個菜,這個菜,還有那個菜。

  [JsonObject(MemberSerialization.OptIn)]   //這個標簽定義了你的選菜方式,只選我要的
    public class PeopleInfo
    {

        [JsonProperty]   //這個標簽標記了這個是你要選擇的菜品

        public string Name { get; set; }

        [JsonProperty]   //這個標簽標記了這個是你要選擇的菜品

        public int Age { get; set; }

        public DateTime Birthday { get; set; }

        public EnumGender Gender { get; set; }

        public List<string> Hobby

        { get; set; }

}

【OptIn情況下,默認是將所有的屬性都定義成了不要,如果這個屬性需要轉換成Json,需要標記JsonProperty】

轉換后的結果:

方式2:就是你去飯店,告訴老板我不要這個菜,不要這個菜。

[JsonObject(MemberSerialization.OptOut)]   //這個標簽定義了你的選菜方式,排除我不要的
    public class PeopleInfo
    {
        public string Name { get; set; }

        [JsonIgnore]  //這個標簽標記了這個不是要想要的菜品
        public int Age { get; set; }
        [JsonIgnore]   //這個標簽標記了這個不是要想要的菜品
        public DateTime Birthday { get; set; }
        public EnumGender Gender { get; set; }
        public List<string> Hobby
        { get; set; }
}

【OptOut情況下,默認是將所有的屬性都定義成了要轉換Json,如果這個屬性不需要轉換成Json,需要標記JsonIgnore】

 

序列化時更改(重命名)屬性名稱;

需求分析:有時候實體類中定義的屬性名稱可能不是想要的名稱,但是又不能更改實體類中屬性的名稱,這個時候就可以自定義序列化字段名稱。

這就好比,飯店里面的一道菜菜單叫螞蟻上樹,實際上就是一道粉絲炒肉末,螞蟻上樹就是重命名的屬性名稱,粉絲炒肉末才是它的實體類名稱;

還是復用前面的代碼,稍微修改下:

public class PeopleInfo
    {
        [JsonProperty(PropertyName = "名稱")] //寫法1
        public string Name { get; set; }             
[JsonProperty("年齡")]   //寫法2
        public int Age { get; set; }
        public DateTime Birthday { get; set; }
        public EnumGender Gender { get; set; }
        public List<string> Hobby
        { get; set; }
    }

轉換后的結果:

 

 

序列化時將非公共變量(private)轉換為Json;

分析:一般情況下,在進行Json轉換的時候,只會對public 成員進行Json轉換,默認情況下,私有成員是不轉換的。

 

只需要在屬性上標記[JsonProperty]就可以了。如下圖:

 

序列化時忽略空值的屬性字段;

分析:上上面的例子中,Name字段為Null值,假如實際前后端數據交互中,Null值的數據返回豈不是很沒有意義?為此,我們

可以設置下,如果值為Null值時,就不進行序列化轉換。

方式1:在屬性成員中指定NullValueHandling方式。

【NullValueHandling:這是每個枚舉值,Ignore忽略空值,Include包含空值】

方式2:通過上面的示例,我們可以發現,可以對單個屬性進行設置,如果一個實體類有20個屬性成員,30個屬性成員,然后,

一個一個去設置豈不是很二,有沒有更高效的方式呢?答案是當然有的啦,看下面,這個方式就不需要在單獨對每一個屬性進行設置了。

代碼:

private void btnJsonDemo_Click(object sender, EventArgs e)
        {
            PeopleInfo p = new PeopleInfo();
            //p.Name = "李家村的二狗子";   //沒有對Name屬性賦值,Name值為Null值
            p.Age = 30;
            p.Birthday = DateTime.Now;
            p.Gender = EnumGender.male;
            p.Hobby = new List<string> { "寫Bug", "釣魚", "看新聞聯播" };

            JsonSerializerSettings setting = new JsonSerializerSettings();
            setting.NullValueHandling = NullValueHandling.Ignore;   //設置全局的Null值處理,JsonSerializerSettings竟然沒有構造函數,一點都不OOP
            string json = JsonConvert.SerializeObject(p, setting);
            this.txtResult.Text = json;
        }

  

轉換結果如下圖:

 

序列化時枚舉值的處理;

分析:在上面的例子中,所轉換的Gender都是int類型的,假如,我們在轉換Json時需要轉換成對應的字符怎么操作呢?

代碼:[JsonConverter(typeof(StringEnumConverter))]

 

根據條件來設置屬性是否序列化;

Json.NET能夠通過在類上放置ShouldSerialize方法來有條件地序列化屬性,要有條件地序列化屬性,需要在對象類中增加一個

與該屬性同名的布爾值的方法,然后使用ShouldSerialize作為方法名稱的前綴,比如你要設置屬性字段Name根據條件來動態決

定是否序列化,則方法名一定要寫成ShouldSerializeName()。方法的返回值必須是bool類型,如果返回true,表示這個屬性可以

序列化,返回false表示不被序列化。

還用以前的PeopleInfo 類,稍微改進下:

public class PeopleInfo
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public DateTime Birthday { get; set; }
        public EnumGender Gender { get; set; }

        public List<string> Hobby { get; set; }

        //注意方法名稱以及方法類型
        public bool ShouldSerializeName()
        {
            if (this.Name == "李四")  //如果名稱是李四,則Name屬性不序列化
                return false;
            return true;
        }
}

  

調用方法:

 

List<PeopleInfo> list = new List<PeopleInfo>();
            PeopleInfo p = new PeopleInfo();
            p.Name = "李二狗";
            p.Age = 30;
            p.Birthday = DateTime.Now;
            p.Gender = EnumGender.male;
            p.Hobby = new List<string> { "寫Bug", "釣魚", "看新聞聯播" };
            list.Add(p);

            PeopleInfo p1 = new PeopleInfo();
            p1.Name = "李四";
            p1.Age = 30;
            p1.Birthday = DateTime.Now;
            p1.Gender = EnumGender.male;
            p1.Hobby = new List<string> { "工作" };
            list.Add(p1);

            string json = JsonConvert.SerializeObject(list);
            this.txtResult.Text = json;

  轉換結果如下圖:

 

問題升級:如果需要兩個或者多個屬性都可以根據條件來序列化?難道要寫很多個方法?

 

根據條件來設置多個屬性是否序列化;

針對上面的問題,如果有多個屬性需要根據條件來序列化怎么辦?我們可以新增一個方法,如下:

public class LimitPropsContractResolver : DefaultContractResolver
    {
        string[] Propertys = null;
        bool IsSerialize;
        public LimitPropsContractResolver(string[] props, bool retain = true)
        {
            this.Propertys = props;
            this.IsSerialize = retain;
        }
        protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            IList<JsonProperty> list = base.CreateProperties(type, memberSerialization);
            return list.Where(p =>
            {
                if (IsSerialize)
                {
                    return Propertys.Contains(p.PropertyName);
                }
                else
                {
                    return !Propertys.Contains(p.PropertyName);
                }
            }).ToList();
        }
}

  調用的時候,只需要把字段名稱傳入string數組中就可以,bool值表示是否需要轉換此字段;調用方法如下:

JsonSerializerSettings settings = new JsonSerializerSettings();
            settings.ContractResolver = new LimitPropsContractResolver(new string[] { "Gender", "Hobby" }, false);
            string json = JsonConvert.SerializeObject(list, settings);

  

 

參考:

官方:https://github.com/JamesNK/Newtonsoft.Json

官方文檔:https://www.newtonsoft.com/json/help/html/Introduction.htm

https://www.cnblogs.com/leonsky/p/3300511.html

http://www.cnblogs.com/yanweidie/p/4605212.html#_label2

感謝官方以及部分原文作者。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM