.NET 8 Preview 7 中 JsonNode 的一些优化

Intro

在 .NET 8 preview 7 中对于 System.Text.Json 也做了一些优化,有一些针对 JsonNode 的新 API,我们来看下示例

Sample

DeepClone &&DeepEquals

新增了 DeepClone 来 clone 一个全新的 JsonNode,和 JsonNode.DeepEquals 来比较两个 JsonNode 的内容是否一致,在之前的版本中可能一般会通过 JsonNode 的 ToJsonString() 获取 JSON 字符串来进行比较,有了这个 API 之后就可以直接比较两个 JsonNode.

var node = JsonNode.Parse("""{"id": 1, "name": "test", "jobs": ["abc", "def"]}""");
ArgumentNullException.ThrowIfNull(node);
var node2 = node.DeepClone();
Console.WriteLine(node2.ToJsonString());
Console.WriteLine("JsonNode.DeepEquals(node, node2) ?? {0}", JsonNode.DeepEquals(node, node2));

输出结果如下:

{"id":1,"name":"test","jobs":["abc","def"]}
JsonNode.DeepEquals(node, node2) ?? True

JsonArray.GetValues

针对 JsonArray 添加了一个 GetValues<T>() 的方法来便捷的获取一个 IEnumerable<T> 对象

var jsonArray = new JsonArray(1, 2, 3, 2);
var values = jsonArray.GetValues<int>()
    .Where(i => i != 2);
foreach (var value in values)
{
    Console.WriteLine(value);
}

输出结果是:

1
3

实现源码也比较简单:

public IEnumerable<T> GetValues<T>()
{
  foreach (JsonNode jsonNode in this.List)
    yield return jsonNode is null ? (T) null : jsonNode.GetValue<T>();
}

GetPropertyName/GetElementIndex

如果我们当前的对象是 JsonObject 中的某一个属性值,我们可以通过 GetPropertyName 来获取当前 property 的名字,类似地我们当前的对象是 JsonArray 中的一个值,可以通过 GetElementIndex 来获取数组索引

var node = JsonNode.Parse("""{"id": 1, "name": "test", "jobs": ["abc", "def"]}""");
ArgumentNullException.ThrowIfNull(node);
Console.WriteLine(node.GetValueKind());
InvokeHelper.TryInvoke(() => Console.WriteLine(node.GetElementIndex()));
InvokeHelper.TryInvoke(() => Console.WriteLine(node.GetPropertyName()));
Console.WriteLine(node["id"]?.GetPropertyName());
Console.WriteLine(node["jobs"]?.AsArray()[1]?.GetElementIndex());

输出结果:

.NET 8 Preview 7 中 JsonNode 的一些优化

output

More

认真观察的话会发现最后的两个 exception 信息有点不太对,这里算是一个 bug,提了一个 issue 应该是 parentNode,具体可以看 https://github.com/dotnet/runtime/issues/90474 目前已经修复,预计会在 RC 2 版本中修复