.NET 6通过System.Text.Json写JSON DOM API

我们常用JSON的方式,是将类对象序列化/反序列化:

var user = new User { Name = "My IO" };
var json = JsonSerializer.Serialize(user);
var newUser = JsonSerializer.Deserialize<User>(json);

而通过System.Text.Json提供的可写JSON DOM API,我们可以跳过创建类,直接操作JSON DOM。.

1,创建JSON DOM

可以使用下面2个类去创建JSON DOM:

  • JsonObject: 创建JSON对象
  • JsonArray: 创建JSON数组

示例代码如下:

var jsonObject = new JsonObject { 
    ["Value"] = "My IO", 
    ["Object"] = new JsonObject { ["Name"] = "My IO Child" },
    ["ObjectArray"] = new JsonArray(
        new JsonObject { 
            ["Name"] = "1",
            ["ValueArray"] = new JsonArray(1, 2),
        },
        new JsonObject {
            ["OtherName"] = "2"
        })
};
var jsonString = jsonObject.ToJsonString(new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine(jsonString);
// 输出
{
  "Value": "My IO",
  "Object": {
    "Name": "My IO Child"
  },
  "ObjectArray": [
    {
      "Name": "1",
      "ValueArray": [
        1,
        2
      ]
    },
    {
      "OtherName": "2"
    }
  ]
}

可以看到,JsonObject和JsonArray可以嵌套使用生成JSON DOM节点树,而每一DOM节点上的属性都用键值对表示,并且同一数组中的不同节点的属性也可以不一样。

2,查找JSON DOM

可以使用下面类去解析JSON DOM:

  • JsonNode: 解析Json字符串并从节点获取值

示例代码如下:

var newJsonObject = JsonNode.Parse(jsonString);           
Console.WriteLine(newJsonObject["ObjectArray"][0]["Name"]);
//输出
1

可以看到,通过属性名和索引轻松访问任意JSON DOM节点。

同时,也可以转换成JsonObject和JsonArray对象,并且可以使用GetValue方法获取强类型的值:

if (newJsonObject["ObjectArray"] is JsonArray jsonArray)
{
    for (int i = 0; i < jsonArray.Count; i++)
    {
        if (jsonArray[i]["Name"] is JsonObject nameObject)
        {
            string name = nameObject.GetValue<string>();
            Console.WriteLine(name);
        }
    }
}
//输出
1

3,修改JSON DOM

可以修改现有节点上的属性值:

newJsonObject["Value"] = "New Value";

也可以为节点加上属性:

newJsonObject["Object"]["NewName"] = "New Name";

甚至增加新节点:

newJsonObject["NewObject"] = new JsonObject { ["Name"] = "New Object" };

4,删除JSON DOM

虽然没有提供删除节点的方法,但是可以通过将节点设为null,序列化时忽略来变通实现:

newJsonObject["Object"]["NewName"] = null;
newJsonObject["NewObject"] = null;
jsonString = jsonObject.ToJsonString(new JsonSerializerOptions { 
    WriteIndented = true, 
    DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull 
    });