【C# 序列化】System.Text.Json.Nodes ---Json數據交換格式 對應C#類


請先閱讀 JSON數據交換格式

Json數據交換格式 對應C#類

System.Text.Json.Nodes:.NET 6

依微軟的計划,System.Text.Json 應取代Newtonsoft.Json(Json.NET),成為 .NET Core/.NET 5+ 奧林匹克指定 JSON 程式庫。System.Text.Json 主打輕巧高效能,但畢竟發展時間尚短,與身經百戰的老將 Json.NET 相比,在功能完整性及可擴充性上仍有點“嫩”。其中我覺得最不便的地方是缺少像 Json.NET 一樣的 JObjec/JArray 物件模型,無法動態巡覽 JSON 屬性或修改內容,更甭提整合 dynamic 動態型別的花式應用。

好消息! .NET 6 起,System.Text.Json 補強了這段,加入 JsonNode、JsonObject、JsonArray、JsonValue 等型別,對映到 Json.NET 的 JToken、JObject、JArray、JValue,允許開發者以物件模型方式建構 JSON 文件,或是將 JSON 文件轉為物件資料結構,進行增刪修改或屬性巡覽,有了這項武器,處理 JSON 文件就更方便了。

 writeable DOM

. net 6提供了處理內存中可寫文檔對象模型(DOM)的類型,用於在數據的結構化視圖中隨機訪問JSON元素。

對於新增操作我們可以使用JsonObject類和JsonArray類去創建JSON DOM:

  • JsonObject:表示創建JSON對象;
  • JsonArray:表示創建JSON數組。

 

 

 

 

 

主要的 API 如下:

  • JsonNode: JSON 文檔中的一個節點,對應 Newtonsoft.Json 里的 JToken,內部有字典字段
  • JsonObject: JSON 對象繼承自JsonNode,對應 Newtonsoft.Json 里的 JObject是字典結構 繼承了JsonValue、ICollection、IDictionary、IEnumerable。
  • JsonArray: JSON 數組繼承自JsonNode,對應 Newtonsoft.Json 里的 JArray,是list結構 繼承了JsonValue、ICollection、IList、IEnumerable。
  • JsonValue: JSON 中的一個值繼承自JsonNode,對應 Newtonsoft.Json 里的 JValue 繼承了IEnumerable。

JsonNode用法

案例一

生成、獲取JsonNode子節點、以及屬性的值

你可以使用 JsonNode.Parse("") 來將一個 JSON 轉換成一個 JsonNode 對象,可以看下面的示例:

 

using System.Text.Json; using System.Text.Json.Nodes; //生成JsonNode節點 JsonNode JObjectNode = JsonNode.Parse(@"{""ShangHai"":""42""}")!;//將string 解析為JsonNode JsonObject JObject = JObjectNode.AsObject()!;//JsonNode 轉化為Object對象 //解析並且轉化成JsonArray JsonArray JArray = JsonNode.Parse(@"[{""HangZhou"":52},{""MyProperty"":true}]")!.AsArray(); //獲取值子節點 JsonNode sun = JArray[1]; Console.WriteLine($"Parent Node:{sun.Parent}"); Console.WriteLine($"Root Node:{sun.Root}"); Console.WriteLine($"JsonNodeOptions:{sun.Options}"); Console.WriteLine(sun.ToJsonString()); //獲取節點的值 Console.WriteLine(JObject["ShangHai"]!.GetValue<string>()); //OR string value = (string)JObject["ShangHai"]!; Console.WriteLine(value); Console.WriteLine(JArray[1]!["MyProperty"]!.GetValue<bool>());

 

案例二

//獲取天氣
HttpClient hc=new HttpClient(); string joson = await hc.GetStringAsync("http://www.weather.com.cn/data/sk/101010100.html"); var weather=JsonNode.Parse(joson); string city=weather["weatherinfo"]["city"].ToJsonString(); Console.WriteLine(city); Console.Read();

 

案例三、

使用對象初始值設定項創建 JsonNode DOM 並進行更改

以下示例介紹如何:

  • 使用對象初始值設定項創建 DOM。
  • 對 DOM 進行更改。

 

using System.Text.Json;
using System.Text.Json.Nodes;
//新增操作
JsonObject jo = new JsonObject
{
    //JsonObject繼承JsonNode ,JsonNode內部有字典和索引(索引會生成一個node)。字典初始值設定項
    ["Message"] = "個人信息",
    ["Father"] = new JsonObject { ["Name"] = "張三" },
    ["Son"] = new JsonArray(
        //JsonArray 內部有一個list和Add()方法。  JsonArray列表初始化設定項
        new JsonObject
        {
            ["Name"] = "張小小",
            ["Pet"] = new JsonArray("小花狗", "小花貓"),
            ["Age"] = ""
        },
        new JsonObject
        {
            ["Name"] = "張大大",
            ["Pet"] = new JsonArray("小狼狗", "小公雞"),
            ["Age"] = 2
        })
};
string jsonString = jo.ToJsonString(new JsonSerializerOptions { WriteIndented = true });
var njo = JsonNode.Parse(jsonString);
Console.WriteLine(jsonString);


//查詢操作

Console.WriteLine(njo["Son"][1]["Name"]!);////運行后輸出 “張大大”

//修改操作
njo["Message"] = "zhagnxiaoxiao";

//當然,我們不僅能改還可以給節點增加屬性和新的節點:

//增加新節點
njo["SearchDate"] = new JsonObject { ["UTC"] = "2021/12/1 00:00:00", ["UTC8"] = "2021/12/ 08:00:00" };
Console.WriteLine(njo.ToJsonString(new JsonSerializerOptions { WriteIndented = true }));
Console.Read();
//刪除操作 對於刪除,.NET6並沒有提供刪除節點的方法,但我們可以使用一個變通的方法來實現,就是通過將節點設為null,序列化時忽略,代碼如下:
njo["SearchDate"] = null;

Console.WriteLine(njo.ToJsonString(new JsonSerializerOptions { WriteIndented = true }));
//寫入流
using MemoryStream ms=new MemoryStream();
Utf8JsonWriter writer = new Utf8JsonWriter(ms);
jo.WriteTo(writer);
writer.Flush();
var jsonString2 = ms.ToArray();
 

 

JsonObject用法

 

 
using System.Text.Json;
using System.Text.Json.Nodes;



//生成JsonNode節點
JsonNode JObjectNode = System.Text.Json.Nodes.JsonNode.Parse(@"{""ShangHai"":42,""HangZhou"":23}")!;//將string 解析為JsonNode

#region 新建一個JsonObject 對象 多種方法
JsonObject JObject = JObjectNode.AsObject()!;//JsonNode 轉化為Object對象

//  方式1
JsonObject JObject1 = new();
JObject["JiangSu"] = 54;
JObject["ShangHai"] = 32;
JObject["HangZhou"] = 44;

//or  方式2  依賴於Add方法
JsonObject JObject2 = new (){ ["ShangHai"] = 42, ["HangZhou"] = 23 };//依賴與Add方法


//or  方式3 依賴於Add方法
JsonObject JObject3 = new();
JObject.Add(KeyValuePair.Create<string, JsonNode>("name3", "value3"!)!);
JObject.Add("name4", "value4");

//or  方式4  索引
JsonObject JObject4 = new JsonObject(
    new[]
    {
        KeyValuePair.Create<string, JsonNode?>("name1", "value1"),
        KeyValuePair.Create<string, JsonNode?>("name2", 2),
    }
);
 
//or 方式5  索引
var dictionary = new Dictionary<string, JsonNode>
{
    ["name1"] = "value1"!,
    ["name2"] = 2
};

JsonObject JObject5 = new JsonObject(dictionary!);

#endregion


//添加Json屬性

JObject.Add("BeJing", 23);
//or 
JObject["YunNan"] = new JsonArray
{
   new JsonObject{["Name"] = "Spot"},
    new JsonObject{["Exp"] = 255},
       new JsonObject{["Exp1"] = 257},
};
//or
JObject["KunMing"] = new JsonArray("Shield", "Sword", "Bottle");
//or



Console.Clear();
Console.WriteLine("添加3個屬性");
Console.WriteLine(JObject.ToJsonString(new JsonSerializerOptions() {  WriteIndented=true}));
Console.Read();


Console.WriteLine(JObject.ContainsKey("BeJing"));//是否包含屬性
Console.WriteLine(JObject.Count);//對象中屬性的個數

Console.WriteLine(JObject["ShangHai"]!.GetValue<int>());

//刪除屬性
JObject.Remove("ShangHai");
//or
var array = JObject["YunNan"]!.AsArray();


//https://blog.darkthread.net/blog/system-text-json-writable-dom/
//array.Remove(array.Single(o => o?.GetValue<string>() == "Bottle"));
//or
var itme = array.Single(o => o.AsObject().ContainsKey("Exp"));
array.Remove(itme);
Console.WriteLine("移除后的數組");
Console.WriteLine(array.ToJsonString(new JsonSerializerOptions() { WriteIndented = true }));
Console.WriteLine("移除后的對象");
Console.WriteLine(JObject.ToJsonString(new JsonSerializerOptions() { WriteIndented = true }));

Console.Read();
//讀取
string HangZhou = (string)JObject["HangZhou"]!;
string YunNan = (string)JObject["YunNan"]![1]!;
JObject["HangZhou"]!.GetValue<string>();

//JsonObject.GetEnumerator
var enumerator=JObject.GetEnumerator();
while (enumerator.MoveNext())
{
    var current=enumerator.Current;
    Console.WriteLine(current.Key);
}

//JsonObject.TryGetPropertyValue
JsonNode  jnode = new JsonArray() ;
if(JObject.TryGetPropertyValue("YunNan", out jnode))
{
    Console.WriteLine(true);
};



JObject.Clear();//清空字典

 

 JsonArray用法

 
using System.Text.Json;
using System.Text.Json.Nodes;

JsonNode obJsonNode= JsonValue.Create("Beijing") ;
JsonNode obJsonNode2 = JsonValue.Create("Toamkomg");

JsonArray jsonArray =new JsonArray {"shanghai","jiangsu" };
jsonArray.Add("yunan");
jsonArray.Add("jiangsu");
jsonArray.Add(obJsonNode);
jsonArray.Insert(0,obJsonNode2);
Console.WriteLine(jsonArray.Contains(obJsonNode));
Console.WriteLine(jsonArray.IndexOf(obJsonNode));
Console.WriteLine(jsonArray.Count);
Console.WriteLine(jsonArray.ToJsonString(new JsonSerializerOptions {PropertyNameCaseInsensitive=true}));
jsonArray.Remove(obJsonNode);
Console.WriteLine(jsonArray.ToJsonString(new JsonSerializerOptions { PropertyNameCaseInsensitive = true }));
jsonArray.RemoveAt(0);
Console.WriteLine(jsonArray.ToJsonString(new JsonSerializerOptions { PropertyNameCaseInsensitive = true }));

 JsonValue.Create用法

 

 

 

System.Text.Json

該命名空間自 2019 年 9 月以來一直存在,但是,只有最近發布的 .NET 6(2021 年 11 月)包含了一種使用 創建和操作 JSON 的方法。System.Text.JsonJsonNode

一個常見的替代方案是使用 ,這是Newtonsoft Json.NET 的一部分,可以在許多.NET項目中看到。JTokenJObjectJArrayJValue

解析Json數據

string data = @" [ {""name"": ""John Doe"",""occupation"": ""gardener""}, {""name"": ""Peter Novak"", ""occupation"": ""driver""} ]"; //文檔解析配置 JsonDocumentOptions jdo=new(){ AllowTrailingCommas=true, CommentHandling= JsonCommentHandling.Skip }; JsonDocument? jscon= JsonDocument.Parse(data); JsonElement je = jscon.RootElement; if (je.ValueKind == JsonValueKind.Array) { JsonElement.ArrayEnumerator enumerateArray = je.EnumerateArray(); JsonElement.ArrayEnumerator users = enumerateArray.GetEnumerator(); while (users.MoveNext()) { var use = users.Current; Console.WriteLine(use.GetProperty("name")); } }

 使用Utf8JsonWriter編寫原始JSON

. net 6引入了使用System.Text.Json.Utf8JsonWriter編寫原始JSON的可能性。

using System.Text.Json;
using System.Text.Json.Nodes;

namespace JsonNodePOCOExample;

public class TemperatureRanges : Dictionary<string, HighLowTemps>
{
}

public class HighLowTemps
{
    public int High { get; set; }
    public int Low { get; set; }
}

public class Program
{
    public static DateTime[]? DatesAvailable { get; set; }

    public static void Main()
    {
        string jsonString =
@"{
  ""Date"": ""2019-08-01T00:00:00"",
  ""Temperature"": 25,
  ""Summary"": ""Hot"",
  ""DatesAvailable"": [
    ""2019-08-01T00:00:00"",
    ""2019-08-02T00:00:00""
  ],
  ""TemperatureRanges"": {
      ""Cold"": {
          ""High"": 20,
          ""Low"": -10
      },
      ""Hot"": {
          ""High"": 60,
          ""Low"": 20
      }
  }
}
";
        // Parse all of the JSON.
        JsonNode forecastNode = JsonNode.Parse(jsonString)!;

        // Get a single value
        int hotHigh = forecastNode["TemperatureRanges"]!["Hot"]!["High"]!.GetValue<int>();
        Console.WriteLine($"Hot.High={hotHigh}");
        // output:
        //Hot.High=60

        // Get a subsection and deserialize it into a custom type.
        JsonObject temperatureRangesObject = forecastNode!["TemperatureRanges"]!.AsObject();
        using var stream = new MemoryStream();
        using var writer = new Utf8JsonWriter(stream);
        temperatureRangesObject.WriteTo(writer);
        writer.Flush();
        TemperatureRanges? temperatureRanges = 
            JsonSerializer.Deserialize<TemperatureRanges>(stream.ToArray());
        Console.WriteLine($"Cold.Low={temperatureRanges!["Cold"].Low}, Hot.High={temperatureRanges["Hot"].High}");
        // output:
        //Cold.Low=-10, Hot.High=60

        // Get a subsection and deserialize it into an array.
        JsonArray datesAvailable = forecastNode!["DatesAvailable"]!.AsArray()!;
        Console.WriteLine($"DatesAvailable[0]={datesAvailable[0]}");
        // output:
        //DatesAvailable[0]=8/1/2019 12:00:00 AM
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM