JSON資料整理

目錄

1.什麼是json

2.json語法規則

3.json基礎結構

4.json基礎示例

5.JSON和XML比較

6. .NET操作JSON

         原始方式

         通用方式

         內置方式

         契約方式

 

通過序列化將.net對象轉換爲JSON字符串

使用LINQ to JSON定製JSON數據

處理客戶端提交的JSON數據

 

1.什麼是JSON

 

JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。它基於JavaScript的一個子集。 JSON採用完全獨立於語言的文本格式,但是也使用了類似於C語言家族的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。這些特性使JSON成爲理想的數據交換語言。易於人閱讀和編寫,同時也易於機器解析和生成。

 

2.JSON語法規則

 

JSON 語法是 JavaScript 對象表示法語法的子集。

l  數據在名稱/值對中

l  數據由逗號分隔

l  花括號保存對象

l  方括號保存數組

 

JSON 數據的書寫格式是:名稱/值對。

名稱/值對包括字段名稱(在雙引號中),後面寫一個冒號,然後是值:

"firstName" : "John"

這很容易理解,等價於這條 JavaScript 語句:

firstName = "John"

 

JSON 值可以是:

l  數字(整數或浮點數)

l  字符串(在雙引號中)

l  邏輯值(true 或 false)

l  數組(在方括號中)

l  對象(在花括號中)

l  null

 

JSON在線校驗格式化工具:bejson

 

3.JSON基礎結構

 

JSON建構有兩種結構

JSON簡單說就是javascript中的對象和數組,所以這兩種結構就是對象和數組兩種結構,通過這兩種結構可以表示各種複雜的結構。

1、對象:對象在js中表示爲“{}”括起來的內容,數據結構爲 {key:value,key:value,...}的鍵值對的結構,在面向對象的語言中,key爲對象的屬性,value爲對應的屬性值,所以很容易理解,取值方法爲 對象.key 獲取屬性值,這個屬性值的類型可以是 數字、字符串、數組、對象幾種。

2、數組:數組在js中是中括號“[]”括起來的內容,數據結構爲 ["java","javascript","vb",...],取值方式和所有語言中一樣,使用索引獲取,字段值的類型可以是 數字、字符串、數組、對象幾種。

經過對象、數組2種結構就可以組合成複雜的數據結構了。

 

4.JSON基礎示例

 

簡單地說,JSON 可以將 JavaScript 對象中表示的一組數據轉換爲字符串,然後就可以在函數之間輕鬆地傳遞這個字符串,或者在異步應用程序中將字符串從 Web 客戶機傳遞給服務器端程序。這個字符串看起來有點兒古怪,但是JavaScript很容易解釋它,而且 JSON 可以表示比"名稱 / 值對"更復雜的結構。例如,可以表示數組和複雜的對象,而不僅僅是鍵和值的簡單列表。

名稱 / 值對

按照最簡單的形式,可以用下面這樣的 JSON 表示"名稱 / 值對":

{ "firstName": "Brett" }

這個示例非常基本,而且實際上比等效的純文本"名稱 / 值對"佔用更多的空間:

firstName=Brett

但是,當將多個"名稱 / 值對"串在一起時,JSON 就會體現出它的價值了。首先,可以創建包含多個"名稱 / 值對"的 記錄,比如:

{ "firstName": "Brett", "lastName":"McLaughlin", "email": "aaaa" }

從語法方面來看,這與"名稱 / 值對"相比並沒有很大的優勢,但是在這種情況下 JSON 更容易使用,而且可讀性更好。例如,它明確地表示以上三個值都是同一記錄的一部分;花括號使這些值有了某種聯繫。

 

表示數組

當需要表示一組值時,JSON 不但能夠提高可讀性,而且可以減少複雜性。例如,假設您希望表示一個人名列表。在XML中,需要許多開始標記和結束標記;如果使用典型的名稱 / 值對(就像在本系列前面文章中看到的那種名稱 / 值對),那麼必須建立一種專有的數據格式,或者將鍵名稱修改爲 person1-firstName這樣的形式。

如果使用 JSON,就只需將多個帶花括號的記錄分組在一起:

1
2
3
4
5
6
7
{
"people": [
                { "firstName": "Brett", "lastName":"McLaughlin", "email": "aaaa" },
                { "firstName": "Jason", "lastName":"Hunter", "email": "bbbb"},
                { "firstName": "Elliotte", "lastName":"Harold", "email": "cccc" }
            ]
}

 

這不難理解。在這個示例中,只有一個名爲 people的變量,值是包含三個條目的數組,每個條目是一個人的記錄,其中包含名、姓和電子郵件地址。上面的示例演示如何用括號將記錄組合成一個值。當然,可以使用相同的語法表示多個值(每個值包含多個記錄):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{ "programmers": [
{ "firstName": "Brett", "lastName":"McLaughlin", "email": "aaaa" },
{ "firstName": "Jason", "lastName":"Hunter", "email": "bbbb" },
{ "firstName": "Elliotte", "lastName":"Harold", "email": "cccc" }
],
"authors": [
{ "firstName": "Isaac", "lastName": "Asimov", "genre": "science fiction" },
{ "firstName": "Tad", "lastName": "Williams", "genre": "fantasy" },
{ "firstName": "Frank", "lastName": "Peretti", "genre": "christian fiction" }
],
"musicians": [
{ "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar" },
{ "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" }
] }

 

這裏最值得注意的是,能夠表示多個值,每個值進而包含多個值。但是還應該注意,在不同的主條目(programmers、authors 和 musicians)之間,記錄中實際的名稱 / 值對可以不一樣。JSON 是完全動態的,允許在 JSON 結構的中間改變表示數據的方式。

在處理 JSON 格式的數據時,沒有需要遵守的預定義的約束。所以,在同樣的數據結構中,可以改變表示數據的方式,甚至可以以不同方式表示同一事物。

 

5.JSON和XML比較

 

可讀性

JSON和XML的可讀性可謂不相上下,一邊是簡易的語法,一邊是規範的標籤形式,很難分出勝負。

可擴展性

XML天生有很好的擴展性,JSON當然也有,沒有什麼是XML能擴展,而JSON卻不能擴展的。不過JSON在Javascript主場作戰,可以存儲Javascript複合對象,有着xml不可比擬的優勢。

編碼難度、解碼難度(略)

 

實例比較

XML和JSON都使用結構化方法來標記數據,下面來做一個簡單的比較。

用XML表示中國部分省市數據如下:

複製代碼
<?xml version="1.0" encoding="utf-8"?>
<country>
    <name>中國</name>
    <province>
        <name>黑龍江</name>
        <cities>
            <city>哈爾濱</city>
            <city>大慶</city>
        </cities>
    </province>
    <province>
        <name>廣東</name>
        <cities>
            <city>廣州</city>
            <city>深圳</city>
            <city>珠海</city>
        </cities>
    </province>
    <province>
        <name>臺灣</name>
        <cities>
            <city>臺北</city>
            <city>高雄</city>
        </cities>
    </province>
    <province>
        <name>新疆</name>
        <cities>
            <city>烏魯木齊</city>
        </cities>
    </province>
</country>
複製代碼

 

用JSON表示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
    "name":"中國",
    "province":[
    {
       "name":"黑龍江",
        "cities":{
            "city":["哈爾濱","大慶"]
        }
     },
     {
        "name":"廣東",
        "cities":{
            "city":["廣州","深圳","珠海"]
        }
    },
    {
        "name":"臺灣",
        "cities":{
            "city":["臺北","高雄"]
        }
    },
    {
        "name":"新疆",
        "cities":{
            "city":["烏魯木齊"]
        }
    }
]
}

 

6. .NET操作JSON

 

JSON文件讀入到內存中就是字符串,.NET操作JSON就是生成與解析JSON字符串。操作JSON通常有以下幾種方式:

1. 原始方式:自己按照JSON的語法格式,寫代碼直接操作JSON字符串。如非必要,應該很少人會走這條路,從頭再來的。

2. 通用方式:這種方式是使用開源的類庫Newtonsoft.Json(下載地址http://json.codeplex.com/)。下載後加入工程就能用。通常可以使用JObject, JsonReader, JsonWriter處理。這種方式最通用,也最靈活,可以隨時修改不爽的地方。

(1)使用JsonReader讀Json字符串:

1
2
3
4
5
6
string jsonText = @"{""input"" : ""value"", ""output"" : ""result""}";
JsonReader reader = new JsonTextReader(new StringReader(jsonText));
while (reader.Read())
{
    Console.WriteLine(reader.TokenType + "\t\t" + reader.ValueType + "\t\t" + reader.Value);
}

 

(2)使用JsonWriter寫字符串:

1
2
3
4
5
6
7
8
9
10
11
StringWriter sw = new StringWriter();
JsonWriter writer = new JsonTextWriter(sw);
writer.WriteStartObject();
writer.WritePropertyName("input");
writer.WriteValue("value");
writer.WritePropertyName("output");
writer.WriteValue("result");
writer.WriteEndObject();
writer.Flush();
string jsonText = sw.GetStringBuilder().ToString();
Console.WriteLine(jsonText);

 

(3)使用JObject讀寫字符串:

1
2
JObject jo = JObject.Parse(jsonText);
string[] values = jo.Properties().Select(item => item.Value.ToString()).ToArray();

 

(4)使用JsonSerializer讀寫對象(基於JsonWriter與JsonReader):

1
2
3
4
5
6
7
8
Project p = new Project() { Input = "stone", Output = "gold" };
JsonSerializer serializer = new JsonSerializer();
StringWriter sw = new StringWriter();
serializer.Serialize(new JsonTextWriter(sw), p);
Console.WriteLine(sw.GetStringBuilder().ToString());
StringReader sr = new StringReader(@"{""Input"":""stone"", ""Output"":""gold""}");
Project p1 = (Project)serializer.Deserialize(new JsonTextReader(sr), typeof(Project));
Console.WriteLine(p1.Input + "=>" + p1.Output);

 

上面的代碼都是基於下面這個Project類定義:

1
2
3
4
5
class Project
{
    public string Input { get; set; }
    public string Output { get; set; }
}

 

此外,如果上面的JsonTextReader等類編譯不過的話,說明是我們自己修改過的類,換成你們自己的相關類就可以了,不影響使用。

3. 內置方式:使用.NET Framework 3.5/4.0中提供的System.Web.Script.Serialization命名空間下的JavaScriptSerializer類進行對象的序列化與反序列化,很直接。

1
2
3
4
5
6
7
Project p = new Project() { Input = "stone", Output = "gold" };
JavaScriptSerializer serializer = new JavaScriptSerializer();
var json = serializer.Serialize(p);
Console.WriteLine(json);
var p1 = serializer.Deserialize<Project>(json);
Console.WriteLine(p1.Input + "=>" + p1.Output);
Console.WriteLine(ReferenceEquals(p,p1));

 

注意:如果使用的是VS2010,則要求當前的工程的Target Framework要改成.Net Framework 4,不能使用Client Profile。當然這個System.Web.Extensions.dll主要是Web使用的,直接在Console工程中用感覺有點浪費資源。

此外,從最後一句也可以看到,序列化與反序列化是深拷貝的一種典型的實現方式。

更新1:

注意用System.Web.Script.Serialization的時候,序列化沒問題,反序列化會將DateTime賦值成了UTC時間。

UTC時間 + 時區差 = 本地時間

6:02 + (+0800) = 14:02(北京時間)

1
2
3
4
5
6
7
DateTime dt = DateTime.Now;
JavaScriptSerializer serializer = new JavaScriptSerializer();
var json = serializer.Serialize(dt);
Console.WriteLine(json);
var dt1 = serializer.Deserialize<DateTime>(json);
Response.Write(dt1.ToString()+"<br />");
Response.Write(ReferenceEquals(dt, dt1));

 關於UTC時間與北京時間的區別請移步:UTC時間與北京時間差多久?

 感謝 @ 老牛吃肉 提醒

 

4. 契約方式:使用System.Runtime.Serialization.dll提供的DataContractJsonSerializer或者 JsonReaderWriterFactory實現。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Project p = new Project() { Input = "stone", Output = "gold" };
DataContractJsonSerializer serializer = new DataContractJsonSerializer(p.GetType());
string jsonText;
  
using (MemoryStream stream = new MemoryStream())
{
    serializer.WriteObject(stream, p);
    jsonText = Encoding.UTF8.GetString(stream.ToArray());
    Console.WriteLine(jsonText);
}
 
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonText)))
{
    DataContractJsonSerializer serializer1 = new DataContractJsonSerializer(typeof(Project));
    Project p1 = (Project)serializer1.ReadObject(ms);
    Console.WriteLine(p1.Input + "=>" + p1.Output);
}

 

這裏要注意,這裏的Project類和成員要加相關的Attribute:

1
2
3
4
5
6
7
8
[DataContract]
class Project
{
    [DataMember]
    public string Input { get; set; }
    [DataMember]
    public string Output { get; set; }
}

 

實用參考:

JSON驗證工具:http://jsonlint.com/

JSON簡明教程:http://www.w3school.com.cn/json/

Newtonsoft.Json類庫下載:http://json.codeplex.com/

 

通過序列化將.net對象轉換爲JSON字符串

 

在web開發過程中,我們經常需要將從數據庫中查詢到的數據(一般爲一個集合,列表或數組等)轉換爲JSON格式字符串傳回客戶端,這就需要進行序列化,這裏用到的是JsonConvert對象的SerializeObject方法。其語法格式爲:JsonConvert.SerializeObject(object),代碼中的”object”就是要序列化的.net對象,序列化後返回的是json字符串。

 

比如,現在我們有一個TStudent的學生表,表中的字段和已有數據如圖所示

 

從表中我們可以看到一共有五條數據,現在我們要從數據庫中取出這些數據,然後利用JSON.NET的JsonConvert對象序列化它們爲json字符串,並顯示在頁面上。C#代碼如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
protected void Page_Load(object sender, EventArgs e)
        {
            using (L2SDBDataContext db = new L2SDBDataContext())
            {
                List<Student> studentList = new List<Student>();
                var query = from s in db.TStudents
                            select new {
                                StudentID=s.StudentID,
                                Name=s.Name,
                                Hometown=s.Hometown,
                                Gender=s.Gender,
                                Brithday=s.Birthday,
                                ClassID=s.ClassID,
                                Weight=s.Weight,
                                Height=s.Height,
                                Desc=s.Desc
                            };
                foreach (var item in query)
                {
                    Student student = new Student { StudentID=item.StudentID,Name=item.Name,Hometown=item.Hometown,Gender=item.Gender,Brithday=item.Brithday,ClassID=item.ClassID,Weight=item.Weight,Height=item.Height,Desc=item.Desc};
                    studentList.Add(student);
                }
                lbMsg.InnerText = JsonConvert.SerializeObject(studentList);
            }
        }

 

輸出結果:

 

從圖中我們可以看到,數據庫中的5條記錄全部取出來並轉化爲json字符串了。

 

使用LINQ to JSON定製JSON數據

 

使用JsonConvert對象的SerializeObject只是簡單地將一個list或集合轉換爲json字符串。但是,有的時候我們的前端框架比如ExtJs對服務端返回的數據格式是有一定要求的,比如下面的數據格式,這時就需要用到JSON.NET的LINQ to JSON,LINQ to JSON的作用就是根據需要的格式來定製json數據。

 

比如經常用在分頁的json格式如代碼:

1
2
3
4
5
6
{
    "total": 5, //記錄總數
    "rows":[
        //json格式的數據列表
    ]
}

 

使用LINQ to JSON前,需要引用Newtonsoft.Json的dll和using Newtonsoft.Json.Linq的命名空間。LINQ to JSON主要使用到JObject, JArray, JProperty和JValue這四個對象,JObject用來生成一個JSON對象,簡單來說就是生成”{}”,JArray用來生成一個JSON數組,也就是”[]”,JProperty用來生成一個JSON數據,格式爲key/value的值,而JValue則直接生成一個JSON值。下面我們就用LINQ to JSON返回上面分頁格式的數據。代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
protected void Page_Load(object sender, EventArgs e)
        {
            using (L2SDBDataContext db = new L2SDBDataContext())
            {
                //從數據庫中取出數據並放到列表list中
                List<Student> studentList = new List<Student>();
                var query = from s in db.TStudents
                            select new
                            {
                                StudentID = s.StudentID,
                                Name = s.Name,
                                Hometown = s.Hometown,
                                Gender = s.Gender,
                                Brithday = s.Birthday,
                                ClassID = s.ClassID,
                                Weight = s.Weight,
                                Height = s.Height,
                                Desc = s.Desc
                            };
                foreach (var item in query)
                {
                    Student student = new Student { StudentID = item.StudentID, Name = item.Name, Hometown = item.Hometown, Gender = item.Gender, Brithday = item.Brithday, ClassID = item.ClassID, Weight = item.Weight, Height = item.Height, Desc = item.Desc };
                    studentList.Add(student);
                }
  
                //基於創建的list使用LINQ to JSON創建期望格式的JSON數據
                lbMsg.InnerText = new JObject(
                        new JProperty("total",studentList.Count),
                        new JProperty("rows",
                                new JArray(
                                        //使用LINQ to JSON可直接在select語句中生成JSON數據對象,無須其它轉換過程
                                        from p in studentList
                                        select new JObject(
                                                new JProperty("studentID",p.StudentID),
                                                new JProperty("name",p.Name),
                                                new JProperty("homeTown",p.Hometown)
                                            )
                                    )
                            )
                    ).ToString();
            }
        }

 

輸出結果爲:

 

 

處理客戶端提交的JSON數據

 

客戶端提交過來的數據一般都是json字符串,有了更好地進行操作(面向對象的方式),所以我們一般都會想辦法將json字符串轉換爲json對象。例如客戶端提交了以下數組格式json字符串。

1
2
3
4
5
[
    {StudentID:"100",Name:"aaa",Hometown:"china"},
    {StudentID:"101",Name:"bbb",Hometown:"us"},
    {StudentID:"102",Name:"ccc",Hometown:"england"}
]

 

在服務端就可以使用JObject或JArray的Parse方法輕鬆地將json字符串轉換爲json對象,然後通過對象的方式提取數據。下面是服務端代碼。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protected void Page_Load(object sender, EventArgs e)
        {
            string inputJsonString = @"
                [
                    {StudentID:'100',Name:'aaa',Hometown:'china'},
                    {StudentID:'101',Name:'bbb',Hometown:'us'},
                    {StudentID:'102',Name:'ccc',Hometown:'england'}
                ]";
            JArray jsonObj = JArray.Parse(inputJsonString);
            string message = @"<table border='1'>
                    <tr><td width='80'>StudentID</td><td width='100'>Name</td><td width='100'>Hometown</td></tr>";
            string tpl = "<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>";
            foreach (JObject jObject in jsonObj)
            {
                message += String.Format(tpl, jObject["StudentID"], jObject["Name"],jObject["Hometown"]);
            }
            message += "</table>";
            lbMsg.InnerHtml = message;
        }

輸出結果:

 

 

當然,服務端除了使用LINQ to JSON來轉換json字符串外,也可以使用JsonConvert的DeserializeObject方法。如下面代碼實現上面同樣的功能。

1
2
3
4
5
List<Student> studentList = JsonConvert.DeserializeObject<List<Student>>(inputJsonString);//注意這裏必須爲List<Student>類型,因爲客戶端提交的是一個數組json
            foreach (Student student in studentList)
            {
                message += String.Format(tpl, student.StudentID, student.Name,student.Hometown);
            }

 

總結:

在客戶端,讀寫json對象可以使用”.”操作符或”["key”]”,json字符串轉換爲json對象使用eval()函數。

在服務端,由.net對象轉換json字符串優先使用JsonConvert對象的SerializeObject方法,定製輸出json字符串使用LINQ to JSON。由json字符串轉換爲.net對象優先使用JsonConvert對象的DeserializeObject方法,然後也可以使用LINQ to JSON。

 

參考來源:

百度百科

http://www.cnblogs.com/dxy1982/archive/2012/02/20/2355619.html

http://www.cnblogs.com/mcgrady/archive/2013/06/08/3127781.html

作者:初行
Q Q:121866673點擊這裏給我發消息
QQ羣:313686804(驗證:博客園)
來源:zxlovenet.cnblogs.com
聲明:本文原創發表於博客園,作者爲初行本文歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則視爲侵權。

引用自:http://www.cnblogs.com/zxlovenet/p/3566802.html
發佈了40 篇原創文章 · 獲贊 11 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章