国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

【.NET深呼吸】如何反序列化動態JSON

2019-11-14 15:50:29
字體:
來源:轉載
供稿:網友

 

.net本身除了支持SOAP、xml、二進制等序列化和反序列化,后來也加入了對JSON的序列化的支持。然而,在實際開發中,常常會遇到結構不確定的JSON對象,這些對象可能是其他代碼動態生成的,你事先無法估計它的結構,甚至它的字段名字是動態改變的。

這種情況下,我們很難用一個固定的類來進行反序列化,后來我嘗試過從DynamicObject類派生出一個自定義的動態類型,希望通過這種方法能夠將動態生成的JSON讀出來,但結果依舊不可;后來我又實現了ISerializable接口,想著自行去控制一下數據的讀取,但仍然未果。

最終我總結出來,只有下面這個方法比較省事,并且可以做到將動態的JSON進行反序列化。

asp.net開發的朋友應該會熟悉一個類——位于System.Web.Script.Serialization命名空間下的javaScriptSerializer類。因為這個類是為Web開發服務的,其實可以用于整個.net框架,即你在WinForm、WPF等程序中依舊可以用。這個類的作用是將指定的JSON字符串進行序列化和反序列化,參與操作的類型可以是固定的,如果JSON是固定結構的,這樣就可行。而對于結構不固定的JSON,這個類可以以字典的形式進行操作,即調用DeserializeObject方法后會返回一個Object類型的對象,實際上這個對象是實現了IDictionary<string, object>接口的,這樣一來,反序列化的結果就可以作為字典來操作。如果JSON里面有嵌套的對象,則返回的字典對象中會嵌套著字典對象。

 

于是,我就寫了這么一個類:

    public sealed class JsonObjectReader    {        PRivate string innerJson = null;        public JsonObjectReader(string json)        {            innerJson = json;        }        public dynamic GetObject()        {            dynamic d = new ExpandoObject();            // 將JSON字符串反序列化            JavascriptSerializer s = new JavaScriptSerializer();            object resobj = s.DeserializeObject(this.innerJson);            // 拷貝數據            IDictionary<string, object> dic = (IDictionary<string, object>)resobj;            IDictionary<string, object> dicdyn = (IDictionary<string, object>)d;            foreach (var item in dic)            {                dicdyn.Add(item.Key, item.Value);            }            return d;        }    }


有人會問我,GetObject方法為什么要返回動態類型?是為了方便操作,ExpandoObject是一種簡單易用并且現成的動態類型,在C#中聲明變量時應用上dynamic關鍵字,告訴編譯器這家伙是動態類型,在編譯檢查時可以“網開一面”。而且,我發現ExpandoObject類是顯式實現了IDictionary<string, object>接口的,說明你還可以把它強制轉換為字典數據來操作。

這種做法一舉兩得,如果方便使用,就當成動態對象來訪問,在不方便使用時,也可以當作字典數據來用。

 

下面舉一個不方便使用動態訪問的例子:

            string json = "{" +                              "/"0592/" : /"廈門市/"," +                              "/"0351/" : /"太原市/"," +                              "/"0411/" : /"大連市/"," +                              "/"0459/" : /"大慶市/"" +                          "}";            JsonObjectReader rd = new JsonObjectReader(json);            dynamic res = rd.GetObject();            IDictionary<string, object> d = (IDictionary<string, object>)res;            foreach (var item in d)            {                Console.WriteLine($"{item.Key} = {item.Value}");            }

大伙會發現,這個JSON你是很難用常規方法進行反序列化的,因為它的字段是城市的區號,是不固定的,在聲明類時你無法事先確定類的屬性或字段成員。同時你也發現,字段名是數字的,就算以動態對象得到結果,你也不能以obj.0459這樣的語法來訪問,因為標識符是不能由數字開頭的。這種情況下不能用動態對象來訪問,但可以把它轉換為字典對象來處理。

得到結果如下圖。

 

 

但是,下面這種用法,因為JSON的字段名不是數字開頭,所以能夠以動態對象的方式訪問。

            json = "{/"Name/":/"小明/", /"Age/":25, /"Email/":/"abcd@dog.cc/"}";            JsonObjectReader rd2 = new JsonObjectReader(json);            dynamic res2 = rd2.GetObject();            Console.WriteLine($"姓名:{res2.Name}");            Console.WriteLine($"年齡:{res2.Age}");            Console.WriteLine($"電郵:{res2.Email}");

 因為Name、Age、Email這些字段不是數字開頭,符號標識符的規范要求,所以后面可以用res2.Name的方式來訪問,就像訪問普通對象實例一樣。

得到的結果如下圖。

 

最后要說明一下的是,這種方法只用于.NET框架的應用程序,如ASP.NET、WPF等。如果是Windows Store App的話,可以使用RT API中的JSON相關的類來處理,這些類都位于Windows.Data.Json命名空間

 

示例代碼下載

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 灵宝市| 吉隆县| 信丰县| 龙川县| 鄱阳县| 襄汾县| 白山市| 恩平市| 秀山| 鸡泽县| 泗阳县| 措美县| 小金县| 宝坻区| 祁门县| 尚志市| 南江县| 将乐县| 社会| 鹤壁市| 温宿县| 邳州市| 上杭县| 韶关市| 安新县| 资兴市| 雷波县| 军事| 双辽市| 德惠市| 桦南县| 怀远县| 冀州市| 本溪| 保山市| 象山县| 鄄城县| 抚州市| 洞口县| 高青县| 龙海市|