2013年9月10日 星期二

[轉貼] 使用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反序列化回來):


開始正文
要使用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字串,改天有空再寫)
要讀取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());
                }
            }
        }
    }



}


執行結果:

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());
        }
    }



}
執行結果:
要讀取JSON字串中的某個訊息最好習慣跑迴圈的方式,這樣寫開發速度會較快
因為以上JSON字串剛好是DataTable轉出來的,所以使用Linq to Json感覺會像平常Linq to SQL一樣

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

這次就來判斷如果此份資料的status為OK的話
就找出results裡formatted_address的地址資訊和geometry裡location的lat和lng的值
還有geometry裡locatioon_type的值
以下為JsonViewer排過的版
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());

                    
                }

                
            }

        }
    }



}

執行結果:
使用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"]);

                    }
                }

                
                
            }

        }
    }



}
執行結果:


總而言之,要取值(JValue)的方式
JObject:使用obj["鍵"]
JProperty:使用prj.Value["鍵"]
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());

        }
    }
}
執行結果:


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

沒有留言:

張貼留言