[ASP.net WebForm] 使用Json.Net第三方套件讀取JSON字串

[ASP.net WebForm] 使用Json.Net第三方套件讀取JSON字串

(JSON的基礎簡介請看這:ASP.NET中JSON的序列化和反序列化)

 

會選擇Json.Net來讀取JSON字串是因為此套件處理方式和之前待的Java Team中,使用的套件超像

而且比起.net framework提供的類別,還可以序列/反序列化字典物件


        Dictionary<string, int> original = new Dictionary<string, int>();
        original.Add("A", 1);
        original.Add("B", 2);
        /*序列化Dictionary物件*/
        string jsonStr = JsonConvert.SerializeObject(original,Formatting.Indented);
        /*Formatting.Indented,這樣的字串輸出在瀏覽器上檢視的話有排版效果較易閱讀*/


        /*顯示結果*/
        Response.Write("Dictionary物件經過序列化:<br/>" + jsonStr + "<hr/>");
        /*JSON字串反序列化為Dictionary物件*/
        Dictionary<string, int> back = (Dictionary<string, int>)JsonConvert.DeserializeObject(jsonStr, typeof(Dictionary<string, int>));
        foreach (string key in back.Keys)
        {
            Response.Write(key + "=>" + back[key] + "<br/>");

        }

結果 (Dictionary物件被序列化後應該可以被當做JObject反序列化回來):

image

 

 

開始正文

要使用Json.NET的話,先到官網:http://json.codeplex.com/

下載紅框處

解壓縮後把Bin\Net資料夾底下的Newtonsoft.Json.dll放到Web Site專案的Bin目錄下即完成加入參考

 

另外

要閱讀JSON字串的話,個人推薦Online JSON Viewer

把JSON字串貼到Text頁籤的畫面上,可以再按Format排版

也可以再按Viewer進一步察看資料

如果JSON格式不符的話,會跳出一個alert訊息

算是輔助Debug的工具

 

 

(此篇文章只紀錄如何讀取JSON字串,至於怎麼產生JSON字串,改天有空再寫:2012.8.16補上[C#.net] 產生JSON字串的幾種方式整理)

要讀取JSON字串中的資訊大概有幾種方法:

1.屠髮練肛土法鍊鋼法:使用JObject、JArray、JProperty的成員一直讀到自己想要的資訊(JValue)

2.Linq to Json

 

 

一開始先從簡單的JSON字串開始習慣吧


[
  {
    "CategoryID": 1,
    "CategoryName": "飲料"
  },
  {
    "CategoryID": 2,
    "CategoryName": "調味品"
  },
  {
    "CategoryID": 3,
    "CategoryName": "點心"
  },
  {
    "CategoryID": 4,
    "CategoryName": "日用品"
  },
  {
    "CategoryID": 5,
    "CategoryName": "穀類/麥片"
  },
  {
    "CategoryID": 6,
    "CategoryName": "肉/家禽"
  },
  {
    "CategoryID": 7,
    "CategoryName": "特製品"
  },
  {
    "CategoryID": 8,
    "CategoryName": "海鮮"
  },
  {
    "CategoryID": 32,
    "CategoryName": "abc"
  }
]

這邊假設我要讀到CategoryID為6,它的CategoryName的值

1.土法鍊鋼法:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using Newtonsoft.Json;
using System.Net;
using System.Web.Configuration;
using System.Text;
using Newtonsoft.Json.Linq;

public partial class ReadJson : System.Web.UI.Page
{
    string WebSiteRoot = WebConfigurationManager.AppSettings["WebSiteRoot"];
    protected void Page_Load(object sender, EventArgs e)
    {

        WebClient wc = new WebClient();
        wc.Encoding = Encoding.UTF8;
        /*載入JSON字串*/
        string jsonStr = wc.DownloadString(this.WebSiteRoot + "returnJSONStr.ashx");

        if (!IsPostBack)//Get Method
        {

            JArray array = JsonConvert.DeserializeObject<JArray>(jsonStr);
            JObject obj = (JObject)array[5];
            /*注意key有分大小寫*/
            Response.Write(obj.Value<string>("CategoryName"));/*取得該CategoryName的值*/
            Response.Write("<br/>");
            Response.Write(obj.Property("CategoryName").Value);/*這樣也可以*/
            Response.Write("<br />");
            Response.Write(obj["CategoryName"]);/*更精簡的寫法*/
            Response.Write("<br />");
            /*或這樣跑迴圈↓*/ 
            foreach (JObject Jobj in array)
            {
                if (Jobj["CategoryID"].ToString() == "6")
                {
                    Response.Write(Jobj["CategoryName"].ToString());
                }
            }
        }
    }



}

 

 

執行結果:

image

 

2.使用Linq to Json


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using Newtonsoft.Json;
using System.Net;
using System.Web.Configuration;
using System.Text;
using Newtonsoft.Json.Linq;

public partial class ReadJson : System.Web.UI.Page
{
    string WebSiteRoot = WebConfigurationManager.AppSettings["WebSiteRoot"];
    protected void Page_Load(object sender, EventArgs e)
    {

        WebClient wc = new WebClient();
        wc.Encoding = Encoding.UTF8;
        /*載入JSON字串*/
        string jsonStr = wc.DownloadString(this.WebSiteRoot + "returnJSONStr.ashx");

        if (!IsPostBack)//Get Method
        {
            JArray array = JsonConvert.DeserializeObject<JArray>(jsonStr);
            var result = from objs in array.Values<JObject>() /*走訪JArray裡每一筆JObject*/
                         where objs["CategoryID"].ToString()=="6"
                         select objs;

            /*只取一筆的值*/
            Response.Write(result.Single<JObject>()["CategoryName"].ToString());
        }
    }



}

執行結果:

image

要讀取JSON字串中的某個訊息最好習慣跑迴圈的方式,這樣寫開發速度會較快

因為以上JSON字串剛好是DataTable轉出來的,所以使用Linq to Json感覺會像平常Linq to SQL一樣

 

習慣之後來找複雜一點的範例當練習

image

 

這次就來判斷如果此份資料的status為OK的話

就找出results裡formatted_address的地址資訊和geometry裡location的lat和lng的值

還有geometry裡locatioon_type的值

以下為JsonViewer排過的版

image


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using Newtonsoft.Json;
using System.Net;
using System.Web.Configuration;
using System.Text;
using Newtonsoft.Json.Linq;
using System.IO;

public partial class ReadJson : System.Web.UI.Page
{
    string WebSiteRoot = WebConfigurationManager.AppSettings["WebSiteRoot"];
    protected void Page_Load(object sender, EventArgs e)
    {

        FileStream fs = new FileStream(Server.MapPath("~/JsonText.txt"), FileMode.Open);
        StreamReader sr = new StreamReader(fs);
        /*載入JSON字串*/
        string jsonStr = sr.ReadToEnd();
        sr.Close();
        fs.Close();
        
        if (!IsPostBack)//Get Method
        {
            JObject obj = JsonConvert.DeserializeObject<JObject>(jsonStr);

            if (obj["status"].ToString()=="OK")
            {
                JArray array = (JArray)obj["results"];
                foreach (JObject obj_results in array)/*走訪JArray(results裡的每一筆JObject(這裡只有一筆)*/
                {
                    Response.Write("formatted_address的值為:" + obj_results["formatted_address"].ToString() + "<br/>");

                    Response.Write("location的lat為:" +obj_results["geometry"]["location"]["lat"].ToString()+"<br/>");
                    Response.Write("location的lng為:" +obj_results["geometry"]["location"]["lng"].ToString()+"<br/>");

                    Response.Write("geometry的location_type為:" + obj_results["geometry"]["location_type"].ToString());

                    
                }

                
            }

        }
    }



}

 

執行結果:

image

使用Linq to Json


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using Newtonsoft.Json;
using System.Net;
using System.Web.Configuration;
using System.Text;
using Newtonsoft.Json.Linq;
using System.IO;

public partial class ReadJson : System.Web.UI.Page
{
    string WebSiteRoot = WebConfigurationManager.AppSettings["WebSiteRoot"];
    protected void Page_Load(object sender, EventArgs e)
    {

        FileStream fs = new FileStream(Server.MapPath("~/JsonText.txt"), FileMode.Open);
        StreamReader sr = new StreamReader(fs);
        /*載入JSON字串*/
        string jsonStr = sr.ReadToEnd();
        sr.Close();
        fs.Close();
        
        if (!IsPostBack)//Get Method
        {
            JObject obj = JsonConvert.DeserializeObject<JObject>(jsonStr);

            if (obj["status"].ToString()=="OK")
            {
                JArray array = (JArray)obj["results"];


                //抓出JArray裡的一筆JObject的所有JProperty
                var result = from Orz in array.Values<JObject>().Single<JObject>().Properties()
                             where Orz.Name == "formatted_address" || Orz.Name == "geometry"
                             select Orz;

                foreach (JProperty item in result)
                {
                    if (item.Name=="formatted_address")
                    {//直接顯示Value
                        Response.Write("formatted_address的值為:" + item.Value.ToString() + "<br/>");
                    }
                    else
                    {//JProperty的Name為geometry 
                        //geometry內含location和location_type兩個鍵值
                        //item.Value["location"]會返回一個JObject
                        Response.Write("location的lat為:" + item.Value["location"]["lat"].ToString() + "<br/>");
                        Response.Write("location的lng為:" + item.Value["location"]["lng"].ToString() + "<br/>");
                        //item.Value["location_type"]會返回一個字串
                        Response.Write("geometry的location_type為:" + item.Value["location_type"]);

                    }
                }

                
                
            }

        }
    }



}

執行結果:

image

 

 

總而言之,要取值(JValue)的方式

JObject:使用obj["鍵"].ToString()

JProperty:使用prj.Value["鍵"].ToString()

JArray:跑迴圈找JObject或指定索引 array[index]

 

 

2011.12.04 追記

DateTime型別的存取


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
/*Json.NET相關的命名空間*/
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)//Get Method
        {

            JObject obj = new JObject();
            obj.Add("now", DateTime.Now);
            string json = JsonConvert.SerializeObject(obj);/*序列化*/
            Response.Write("一個JObject物件=>"+json+"<hr/>");

            
            JObject obj_back = JsonConvert.DeserializeObject<JObject>(json);/*反序列化*/
            Response.Write("將JSON字串轉回JObject物件再取出now的JValue=>" + obj_back["now"] + "<hr/>");
            obj_back = JObject.Parse(json);/*也可以這樣將JSON字串轉回JObject*/
            Response.Write("將JSON字串轉回JObject物件再取出now的JValue=>" + obj_back["now"] + "<hr/>");
            DateTime myDT = Convert.ToDateTime(obj_back["now"].ToString());
            Response.Write("再轉成DateTime物件=>"+myDT.ToString());

        }
    }
}

執行結果:

image

 

 

2012.8.16 追記

如果要讀取的Json字串結構很複雜很巢狀的話

這裡再提供一個利用IDE工具intellisense的「物件存取」方法:

同樣以Google API的這篇最後一組字串當範例:

1. 先把Json字串全部複製

image

2. 接著定義類別,類別不用自己寫,用線上工具產生即可

json2csharp把剛剛複製的Json字串貼上,按下Generate鈕

image

3. Visual Studio新增一個類別檔.cs

把剛剛複製的類別字串貼上即可

image

4.再來寫程式把Json字串讀進來再用JsonConvert.DeserializeObject反序列化為RootObject物件就可以存取了

image

 

 

 

Json.NET官方說明文件:http://james.newtonking.com/projects/json/help/

衍伸閱讀文章:[ASP.net WebForm] 利用JSON.net 實現 DataTable轉JSON字串、JSON字串轉DataTable

[C#]Json.NET - A high performance Json library  

LINQ to JSON 官方API