none
JSON字串利用Deserialize轉成物件集合 RRS feed

  • 問題

  • 我在練習題目時遇到些瓶頸。

    題目說要將JSON 文字檔透過下列的Deserialize 函式,指定轉成Test.cs的物件集合

    public List<T> Deserialize<T>(string json)
    {
    	List<T> result;
    	using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
    	{
    	  DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Test));
    	  result = serializer.ReadObject(ms);
    	}
    	return result;
    }

    上方粗斜體錯誤:類型 'object' 不能隱含轉換為 'System.Collections.Generic.List<T>'。已有明確轉換存在 (您是否漏掉了轉型?)

    Test.cs檔如下

    namespace CSharp_1
    {
        [DataContract]
        class Test
        {
            [DataMember(Name = "name")]
            public string 姓名 { get; set; }
            [DataMember(Name = "sex")]
            public string 性別 { get; set; }
            [DataMember(Name = "age")]
            public string 年齡 { get; set; }
    
        }
    }

    請問我要怎麼修改Desarialize函式,或是除了修改之外還要新增甚麼東西呢??

    謝謝大家!


    • 已編輯 LYK_TW 2015年8月10日 上午 09:55
    2015年8月10日 上午 09:45

解答

  • result = (List<T>)serializer.ReadObject(ms);
    • 已標示為解答 LYK_TW 2015年8月10日 下午 02:15
    2015年8月10日 上午 10:00
  • 你的這個方法其實有點奇怪。

    因為你是用泛型的方式在寫這個方法,但是裡面又寫死說指接受Test形態。

    所以你這一行:

    DataContractJsonSerializer serializer =
    new DataContractJsonSerializer(typeof(Test));

    應該是

    DataContractJsonSerializer serializer =
    new DataContractJsonSerializer(typeof(T)); 

    最後呼叫就是用

    Deserialize<Test>(jsonString);


    • 已編輯 AlanTsai 2015年8月10日 上午 10:49
    • 已標示為解答 LYK_TW 2015年8月10日 下午 02:15
    2015年8月10日 上午 10:47
  • public class Test
        {
            //"rownumber": "179"
            public int rownumber { get; set; }
    
            //"ref_wp": "10"
            public int ref_wp { get; set; }
    
            //"cat1": "景點"
            public string cat1 { get; set; }
    
            //"cat2": "藍色公路"
            public string cat2 { get; set; }
    
            //"serial_no": "2013071000000003"
            public string serial_no { get; set; }
    
            //"memo_tel": "02-2720-8889"
            public string memo_tel { get; set; }
            
            //, "memo_fax": ""
            public string memo_fax { get; set; }
            
            //, "memo_cost": ""
            public string memo_cost { get; set; }
            
            //, "memo_time": "平常日以團體預約包船為主,例假日行駛固定航次,請洽詢各船公司。\n強烈季風、漲退潮水位差影響航行及靠泊安全,當日實際航班得由現場公告或網站預告調整。"
            public string memo_time { get; set; }
            
            //, "stitle": "藍色公路-大稻埕"
            public string stitle { get; set; }
            
            //, "xbody": "臺北市藍色公路於93年2月7日開航以來,目前本市淡水河及基隆河的固定航線已有7條,旅客可由本市大稻埕碼頭乘船往返關渡、淡水老街、八里、八里龍形及淡水漁人碼頭等熱門景點,並可配合河濱自行車道遊程,參訪雙北著名觀光景點如台北霞海城隍廟、關渡宮、關渡自然公園、八里左岸、十三行博物館、漁人碼頭、紅樹林自然保留區、紅毛城、淡水老街等。行駛路線起站迄站航行區域 業者資訊大稻埕─關渡大稻埕碼頭關渡碼頭內河http://www.pto.taipei.gov.tw/ct.asp?xItem=1201275&ctNode=35862&mp=117041大稻埕─淡水老街大稻埕碼頭淡水老街大稻埕─漁人碼頭大稻埕碼頭淡水漁人碼頭大稻埕─八里大稻埕碼頭八里龍形碼頭內河"
            public string xbody { get; set; }
            
            //, "avbegin": "2013-07-10"
            public string avbegin { get; set; }
            
            //, "avend": "2013-10-24"
            public string avend { get; set; }
            
            //, "idpt": "臺北旅遊網"
            public string idpt { get; set; }
    
            //, "xurl": ""
            public string xurl { get; set; }
            
            //, "address": "臺北市  大同區大稻埕碼頭"
            public string address { get; set; }
            
            //, "xpostdate": "2013-10-24"
            public string xpostdate { get; set; }
            
            //, "langinfo": "10"
            public string langinfo { get; set; }
            
            //, "poi": "Y"
            public string poi { get; set; }
            
            //, "info": "捷運站名:雙連站,轉乘紅33(固定班次)於大稻埕碼頭站下車。公車:9、206、274、641、669、704至大稻埕碼頭站及255、518、539至民生西路口站,再沿民生西路底方向步行約10分鐘抵達。 開車:沿著環河北路依大稻埕碼頭入口指引便可抵達"
            public string info { get; set; }
            
            //, "longitude": "121.507856"
            public double longitude { get; set; }
            
            //, "latitude": "25.056747"
            public double latitude { get; set; }
            
            //, "mrt": "雙連"
            public string mrt { get; set; }
            
            //, "servicetype": ""
            public string servicetype { get; set; }
            
            //, "file": "<file><img description=\"藍色公路大稻埕.jpg\">http://www.taipeitravel.net/d_upload_ttn/sceneadmin/image/A0/B0/C0/D22/E140/F715/1831a539-09a4-4a77-9950-9f4a6373c40c.jpg</img></file>" }
            public string file { get; set; }
        }


    public T Deserialize<T>(string json)
            {
                var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
                T result;
                using (var mStream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
                {
                    result = (T)serializer.ReadObject(mStream);
                }
                return result;
            }
    
            public string GetJson()
            {
                return File.ReadAllText(@"C:\檔案實體路徑\data.json");
            }

    呼叫

    var result = Deserialize<List<Test>>(GetJson());

    • 已標示為解答 LYK_TW 2015年8月10日 下午 02:09
    2015年8月10日 下午 12:43

所有回覆

  • 你方便把json的格式貼出來嗎?!?!
    2015年8月10日 上午 09:57
  • result = (List<T>)serializer.ReadObject(ms);
    • 已標示為解答 LYK_TW 2015年8月10日 下午 02:15
    2015年8月10日 上午 10:00
  • 你方便把json的格式貼出來嗎?!?!

    您好,其實這JSON檔很多欄位,所以我把Test.cs內的DataMember都簡化了

    不過我有將JSON原檔上傳到我的雲端硬碟了,這是台北市的旅遊景點清單。

    https://drive.google.com/file/d/0B76chVfbT2gTWTFsNUU1aVg0MWM/view?usp=sharing


    2015年8月10日 上午 10:15
  • result = (List<T>)serializer.ReadObject(ms);
    謝謝!那請問前輩,如果我今天已經將JSON字串ReadToEnd,JSON字串有讀進來了
    我要如何將JSON字串進入這個Deserialize函式呢?
    還請協助小弟!!
    2015年8月10日 上午 10:19
  • 你的這個方法其實有點奇怪。

    因為你是用泛型的方式在寫這個方法,但是裡面又寫死說指接受Test形態。

    所以你這一行:

    DataContractJsonSerializer serializer =
    new DataContractJsonSerializer(typeof(Test));

    應該是

    DataContractJsonSerializer serializer =
    new DataContractJsonSerializer(typeof(T)); 

    最後呼叫就是用

    Deserialize<Test>(jsonString);


    • 已編輯 AlanTsai 2015年8月10日 上午 10:49
    • 已標示為解答 LYK_TW 2015年8月10日 下午 02:15
    2015年8月10日 上午 10:47
  • 你的函式回傳是 List<T>,

    new DataContractJsonSerializer(typeof(Test)); <-- 這邊也應該是 typeof(List<T>) 吧

    對了, 如果不是使用 WCF , 其實用 Newton Json.Net (你可以在 NuGet 套件找到) 比較簡單.



    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    2015年8月10日 上午 11:41
    版主
  • public class Test
        {
            //"rownumber": "179"
            public int rownumber { get; set; }
    
            //"ref_wp": "10"
            public int ref_wp { get; set; }
    
            //"cat1": "景點"
            public string cat1 { get; set; }
    
            //"cat2": "藍色公路"
            public string cat2 { get; set; }
    
            //"serial_no": "2013071000000003"
            public string serial_no { get; set; }
    
            //"memo_tel": "02-2720-8889"
            public string memo_tel { get; set; }
            
            //, "memo_fax": ""
            public string memo_fax { get; set; }
            
            //, "memo_cost": ""
            public string memo_cost { get; set; }
            
            //, "memo_time": "平常日以團體預約包船為主,例假日行駛固定航次,請洽詢各船公司。\n強烈季風、漲退潮水位差影響航行及靠泊安全,當日實際航班得由現場公告或網站預告調整。"
            public string memo_time { get; set; }
            
            //, "stitle": "藍色公路-大稻埕"
            public string stitle { get; set; }
            
            //, "xbody": "臺北市藍色公路於93年2月7日開航以來,目前本市淡水河及基隆河的固定航線已有7條,旅客可由本市大稻埕碼頭乘船往返關渡、淡水老街、八里、八里龍形及淡水漁人碼頭等熱門景點,並可配合河濱自行車道遊程,參訪雙北著名觀光景點如台北霞海城隍廟、關渡宮、關渡自然公園、八里左岸、十三行博物館、漁人碼頭、紅樹林自然保留區、紅毛城、淡水老街等。行駛路線起站迄站航行區域 業者資訊大稻埕─關渡大稻埕碼頭關渡碼頭內河http://www.pto.taipei.gov.tw/ct.asp?xItem=1201275&ctNode=35862&mp=117041大稻埕─淡水老街大稻埕碼頭淡水老街大稻埕─漁人碼頭大稻埕碼頭淡水漁人碼頭大稻埕─八里大稻埕碼頭八里龍形碼頭內河"
            public string xbody { get; set; }
            
            //, "avbegin": "2013-07-10"
            public string avbegin { get; set; }
            
            //, "avend": "2013-10-24"
            public string avend { get; set; }
            
            //, "idpt": "臺北旅遊網"
            public string idpt { get; set; }
    
            //, "xurl": ""
            public string xurl { get; set; }
            
            //, "address": "臺北市  大同區大稻埕碼頭"
            public string address { get; set; }
            
            //, "xpostdate": "2013-10-24"
            public string xpostdate { get; set; }
            
            //, "langinfo": "10"
            public string langinfo { get; set; }
            
            //, "poi": "Y"
            public string poi { get; set; }
            
            //, "info": "捷運站名:雙連站,轉乘紅33(固定班次)於大稻埕碼頭站下車。公車:9、206、274、641、669、704至大稻埕碼頭站及255、518、539至民生西路口站,再沿民生西路底方向步行約10分鐘抵達。 開車:沿著環河北路依大稻埕碼頭入口指引便可抵達"
            public string info { get; set; }
            
            //, "longitude": "121.507856"
            public double longitude { get; set; }
            
            //, "latitude": "25.056747"
            public double latitude { get; set; }
            
            //, "mrt": "雙連"
            public string mrt { get; set; }
            
            //, "servicetype": ""
            public string servicetype { get; set; }
            
            //, "file": "<file><img description=\"藍色公路大稻埕.jpg\">http://www.taipeitravel.net/d_upload_ttn/sceneadmin/image/A0/B0/C0/D22/E140/F715/1831a539-09a4-4a77-9950-9f4a6373c40c.jpg</img></file>" }
            public string file { get; set; }
        }


    public T Deserialize<T>(string json)
            {
                var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
                T result;
                using (var mStream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
                {
                    result = (T)serializer.ReadObject(mStream);
                }
                return result;
            }
    
            public string GetJson()
            {
                return File.ReadAllText(@"C:\檔案實體路徑\data.json");
            }

    呼叫

    var result = Deserialize<List<Test>>(GetJson());

    • 已標示為解答 LYK_TW 2015年8月10日 下午 02:09
    2015年8月10日 下午 12:43
  • 謝謝前輩!!您的程式碼對我幫助我很多,謝謝抽空解答!!


    • 已編輯 LYK_TW 2015年8月10日 下午 02:13
    2015年8月10日 下午 02:09
  • 謝謝您的回覆,我對List<T>的部分會再自我修行。

    我當初也是想用Json.net,想不到題目指定用DataContractJsonSerializer@@

    • 已標示為解答 LYK_TW 2015年8月10日 下午 02:12
    • 已取消標示為解答 LYK_TW 2015年8月10日 下午 02:12
    2015年8月10日 下午 02:11
  • 謝謝您的回覆,讓我對泛型的部分長了點知識,謝謝!
    也謝謝提供呼叫Deserialize函式的方法
    • 已編輯 LYK_TW 2015年8月10日 下午 02:15
    2015年8月10日 下午 02:14
  • 謝謝協助回答問題!!
    2015年8月10日 下午 02:17