JSON.NET與LINQ序列化示例

風靈使發表於2018-10-13

這篇文章通過多個示例演示JSON.NETLINQ的完美結合,讓.NET操作JSON變得非常的簡單,最後我們還會演示如何通過JSON.NET轉換BSON資料、如何實現JSON格式與XML格式的互相轉換,讓您熟練在.NET中序列化物件。

1、手動建立JSON物件和陣列

JSON格式主要包括物件陣列兩種形式,在JSON.NET中分別用JArrayJObject表示,屬性用JProperty表示,屬性值用JValue表示,這些物件都直接或間接繼承JToken抽象類,而且都有一個ToString方法,該方法用於直接輸出元素的JSON字串表示形式,我們可以通過JArrayJObject手動建立JSON並序列化,使用方式非常靈活。

JArray array = new JArray();
array.Add("Manual text");
array.Add(new DateTime(2000, 5, 23));
JObject o = new JObject();
o["MyArray"] = array;
string json = o.ToString();
{
  "MyArray": [
    "Manual text",
    "2000-05-23T00:00:00"
  ]
}

2、用集合的方式初始化JArray陣列和JObject物件

JObject o = new JObject { { "Cpu", "Intel" }, { "Memory", 32 }, { "Drives", new JArray { "DVD", "SSD" } } };
Console.WriteLine(o.ToString());
{
  "Cpu": "Intel",
  "Memory": 32,
  "Drives": [
    "DVD",
    "SSD"
  ]
}

3、使用動態型別dynamic型別建立JSON陣列和物件

C#中的動態型別dynamic允許開發者動態構造物件,這些動態構造的物件在執行時被解析執行,JSON.NET支援動態型別,無需定義類,即可構造JSON,這一些就像在JavaScript中編寫一個物件那樣簡單,正是因為動態型別在執行時才被解析,所以,在開發工具中不能檢查因書寫而導致錯誤,這點一定要注意。

dynamic product = new JObject();
product.ProductName = "Elbow Grease";
product.Enabled = true;
product.Price = 4.90m;
product.StockCount = 9000;
product.StockValue = 44100;
product.Tags = new JArray("Real", "OnSale");
Console.WriteLine(product.ToString());
{
  "ProductName": "Elbow Grease",
  "Enabled": true,
  "Price": 4.90,
  "StockCount": 9000,
  "StockValue": 44100,
  "Tags": [
    "Real",
    "OnSale"
  ]
}

4、使用JTokenWriter建立物件和陣列

JTokenWriter writer = new JTokenWriter();
writer.WriteStartObject();
writer.WritePropertyName("name1");
writer.WriteValue("value1");
writer.WritePropertyName("name2");
writer.WriteStartArray();
writer.WriteValue(1);
writer.WriteValue(2);
writer.WriteEndArray();
writer.WriteEndObject();
JObject o = (JObject)writer.Token;
Console.WriteLine(o.ToString());

{
  "name1": "value1",
  "name2": [
    1,
    2
  ]
}

5、使用物件建立JSON物件和陣列

JTokenJObjectJArray都提供一個名為FromObject的方法,允許通過一個物件來建立JSON物件。

Computer computer = new Computer
{
    Cpu = "Intel",
    Memory = 32,
    Drives = new List<string> { "DVD", "SSD" }
};
JObject o = (JObject)JToken.FromObject(computer);
Console.WriteLine(o.ToString());
{
  "Cpu": "Intel",
  "Memory": 32,
  "Drives": [
    "DVD",
    "SSD"
  ]
}

JArray a = (JArray)JToken.FromObject(computer.Drives);
Console.WriteLine(a.ToString());
[
  "DVD",
  "SSD"
]

6、使用字串建立JSON物件和陣列

string json = @"['Small', 'Medium','Large']";
JArray a = JArray.Parse(json);
Console.WriteLine(a.ToString());
[
  "Small",
  "Medium",
  "Large"
]

string json = @"{
    CPU: 'Intel',
    Drives: [
      'DVD read/writer',
      '500 gigabyte hard drive'
    ]
  }";
JObject o = JObject.Parse(json);
Console.WriteLine(o.ToString());
{
  "CPU": "Intel",
  "Drives": [
    "DVD read/writer",
    "500 gigabyte hard drive"
  ]
}

7、使用JToken轉換JSON字串

在示例1中,我們已經說明JToken型別,它是JSON.NET的核心,幾乎所有的JSON元素都繼承於JToken抽象類,雖然JToken是抽象類,但它也提供一些很有用的基礎方法,可以轉換一段字串並判斷它應有的JSON型別。


JToken t1 = JToken.Parse("{}");
Console.WriteLine(t1.Type);
// Object

JToken t2 = JToken.Parse("[]");
Console.WriteLine(t2.Type);
// Array

JToken t3 = JToken.Parse("null");
Console.WriteLine(t3.Type);
// Null

JToken t4 = JToken.Parse(@"'A string!'");
Console.WriteLine(t4.Type);
// String

8、動態修改JSON物件和陣列

string json = @"{
     'channel': {
       'title': 'Star Wars',
       'link': 'www.xcode.me',
       'description': 'Star Wars blog.',
       'obsolete': 'Obsolete value',
       'item': []
     }
   }";
JObject rss = JObject.Parse(json);
JObject channel = (JObject)rss["channel"];
channel["title"] = ((string)channel["title"]).ToUpper();
channel["description"] = ((string)channel["description"]).ToUpper();
channel.Property("obsolete").Remove();
channel.Property("description").AddAfterSelf(new JProperty("new", "New value"));
JArray item = (JArray)channel["item"];
item.Add("Item 1");
item.Add("Item 2");
Console.WriteLine(rss.ToString());
{
  "channel": {
    "title": "STAR WARS",
    "link": "www.xcode.com",
    "description": "STAR WARS BLOG.",
    "new": "New value",
    "item": [
      "Item 1",
      "Item 2"
    ]
  }
}

9、合併兩個JSON物件

JObject o1 = JObject.Parse(@"{
      'FirstName': 'John',
      'LastName': 'Smith',
      'Enabled': false,
      'Roles': [ 'User' ]
    }");
JObject o2 = JObject.Parse(@"{
      'Enabled': true,
      'Roles': [ 'User', 'Admin' ]
    }");
o1.Merge(o2, new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Union });
string json = o1.ToString();
{
  "FirstName": "John",
  "LastName": "Smith",
  "Enabled": true,
  "Roles": [
    "User",
    "Admin"
  ]
}

這裡要特別說明的是JsonMergeSettings,該物件用於設定合併時的行為,MergeArrayHandling是列舉,可設定為Concat(連線陣列)、Union(跳過存在的元素,新增不存在的元素)、Replace(替換所有陣列項)和Merge(根據陣列索引將陣列項合併在一起)。

10、使用動態型別dynamic查詢JSON物件

string json = @"[
  {
    'Title': 'Json.NET is awesome!',
    'Author': {
      'Name': 'James Newton-King',
      'Twitter': '@JamesNK',
      'Picture': '/jamesnk.png'
    },
    'Date': '2013-01-23T19:30:00'
  }
]";

dynamic blogPosts = JArray.Parse(json);
dynamic blogPost = blogPosts[0];
Console.WriteLine(blogPost.Title);
Json.NET is awesome!

11、使用ToObjectJSON物件或陣列轉換成C#物件

string json = @"{
   'd': [
     {
       'Name': 'John Smith'
     },
     {
       'Name': 'Mike Smith'
     }
   ]
 }";
JObject o = JObject.Parse(json);
JArray a = (JArray)o["d"];
IList<Person> person = a.ToObject<IList<Person>>();
Console.WriteLine(person[1].Name);
Mike Smith

12、通過屬性遍歷JObject物件

JObject o = new JObject { { "name1", "value1" }, { "name2", "value2" } };
foreach (JProperty property in o.Properties())
{
    Console.WriteLine(property.Name + " - " + property.Value);
}


name1 - value1
name2 - value2
foreach (KeyValuePair<string, JToken> property in o)
{
    Console.WriteLine(property.Key + " - " + property.Value);
}
name1 - value1
name2 - value2

13、使用ToString方法進行JSON序列化

JSON.NETToString方法會輸出針對當前JSON物件的字串表示形式,通過這個特點我們可以序列化物件,預設情況下會輸出格式化後的JSON字串,ToString方法提供一些過載,允許開發靈活配置序列化行為。

JObject o = JObject.Parse(@"{'string1':'value','integer2':99,'datetime3':'2000-05-23T00:00:00'}");
Console.WriteLine(o.ToString());
{
  "string1": "value",
  "integer2": 99,
  "datetime3": "2000-05-23T00:00:00"
}

ToString方法也提供一個是否格式化過載方法,下面的示例演示輸出壓縮後的JSON字串。

Console.WriteLine(o.ToString(Formatting.None));
{"string1":"value","integer2":99,"datetime3":"2000-05-23T00:00:00"}

下面的程式碼演示通過ToString方法提供的過載將日期格式化為JavaScript中的日期物件,這樣的JSONJS中就可以直接使用日期。

Console.WriteLine(o.ToString(Formatting.None, new JavaScriptDateTimeConverter()));
{"string1":"value","integer2":99,"datetime3":new Date(959032800000)}

14、JSON.NET支援BSON格式的序列化和反序列化

BSON是一種類似於JSON格式,是一種二進位制形式儲存格式,簡稱BinaryJSON,它和JSON一樣,支援內嵌的物件和陣列,BSON可以做為網路資料交換的一種儲存形式,它的優點是靈活性高,但它的缺點是空間利用率不是很理想,JSON.NET也支援BSON的序列化和反序列化。

byte[] data = Convert.FromBase64String("KQAAAAJuYW1lMQAHAAAAdmFsdWUxAAJuYW1lMgAHAAAAdmFsdWUyAAA=");
MemoryStream ms = new MemoryStream(data);
JObject o;
using (BsonReader reader = new BsonReader(ms))
{
    o = (JObject)JToken.ReadFrom(reader);
}
string value = (string)o["name1"];
Console.WriteLine(value);
value1
JObject o = new JObject { { "name1", "value1" }, { "name2", "value2" } };
MemoryStream ms = new MemoryStream();
using (BsonWriter writer = new BsonWriter(ms))
{
    o.WriteTo(writer);
}
string data = Convert.ToBase64String(ms.ToArray());
Console.WriteLine(data);
KQAAAAJuYW1lMQAHAAAAdmFsdWUxAAJuYW1lMgAHAAAAdmFsdWUyAAA=

15、JSON.NET也支援JSONXML資料格式之間的互轉

string json = @"{
  '@Id': 1,
  'Email': 'james@example.com',
  'Active': true,
  'CreatedDate': '2013-01-20T00:00:00Z',
  'Roles': [
    'User',
    'Admin'
  ],
  'Team': {
    '@Id': 2,
    'Name': 'Software Developers',
    'Description': 'Creators of fine software products and services.'
  }
}";
XNode node = JsonConvert.DeserializeXNode(json, "Root");
Console.WriteLine(node.ToString());
<Root Id="1">
  <Email>james@example.com</Email>
  <Active>true</Active>
  <CreatedDate>2013-01-20T00:00:00Z</CreatedDate>
  <Roles>User</Roles>
  <Roles>Admin</Roles>
  <Team Id="2">
    <Name>Software Developers</Name>
    <Description>Creators of fine software products and services.</Description>
  </Team>
</Root>
string xml = @"<?xml version='1.0' standalone='no'?>
 <root>
   <person id='1'>
   <name>Alan</name>
   <url>www.xocde.me</url>
   </person>
   <person id='2'>
   <name>Louis</name>
   <url>www.xocde.me</url>
   </person>
 </root>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string json = JsonConvert.SerializeXmlNode(doc);
Console.WriteLine(json);
{
  "?xml": {
    "@version": "1.0",
    "@standalone": "no"
  },
  "root": {
    "person": [
      {
        "@id": "1",
        "name": "Alan",
        "url": "www.xocde.me"
      },
      {
        "@id": "2",
        "name": "Louis",
        "url": "www.xocde.me"
      }
    ]
  }
}

當然,JSON.NET框架很強大,功能也很多,總結都是JSON.NETLINQ結合的常用示例,希望對您有所幫助。

相關文章