使用 System.Text.Json (.NET 6) 获取 JSON 的所有路径和类型

Get all path and types of a JSON with System.Text.Json (.NET 6)

我编写了以下方法来获取 JSON.NET 中 JSON 中所有键的 Path + Type 的所有组合:

public static IEnumerable<string> GetKeys(this JToken jToken)
{
    var keys = new List<string>();

    var jTokenKey = $"{(string.IsNullOrEmpty(jToken.Path) ? "{/ROOT/}" : jToken.Path)}-{jToken.Type}";
    keys.Add(jTokenKey);
    foreach (var child in jToken.Children())
    {
        var key = child.GetKeys();
        keys.AddRange(key);
    }
    return keys;
}

我需要 Path + Type 的组合,用于 JSON 的所有元素。

任何人都可以帮助我获得与 System.Text.Json 相同(或相似)的结果吗?

样本:

{
    "a": [{
            "b": "bbb",
            "c": "ccc",
            "d": "ddd"
        }
    ],
    "e": "2021-12-29T14:20:21.948Z",
    "f": {
        "g": [{
                "h": "hhh",
                "i": "iii",
                "j": null,
                "k": true,
                "l": false,
                "m": "2021-12-29T14:20:21.948Z",
                "n": 10
            }
        ]
    }
}

JSON.NET 结果:

$-Object
a-Property
a-Array
a[0]-Object
a[0].b-Property
a[0].b-String
a[0].c-Property
a[0].c-String
a[0].d-Property
a[0].d-String
e-Property
e-Date
f-Property
f-Object
f.g-Property
f.g-Array
f.g[0]-Object
f.g[0].h-Property
f.g[0].h-String
f.g[0].i-Property
f.g[0].i-String
f.g[0].j-Property
f.g[0].j-Null
f.g[0].k-Property
f.g[0].k-Boolean
f.g[0].l-Property
f.g[0].l-Boolean
f.g[0].m-Property
f.g[0].m-Date
f.g[0].n-Property
f.g[0].n-Integer

您可以使用 JsonDocument API,它允许以某种类似于 Newtonsoft 的方式解析和操作 json。像这样(需要一些工作才能完全表示所需的格式):

IEnumerable<string> EnumeratePaths(JsonElement doc)
{
    var queu = new Queue<(string ParentPath, JsonElement element)>();
    queu.Enqueue(("", doc));
    while (queu.Any())
    {
        var (parentPath, element) = queu.Dequeue();
        switch (element.ValueKind)
        {
            case JsonValueKind.Object:
                parentPath = parentPath == ""
                    ? parentPath
                    : parentPath + ".";
                foreach (var nextEl in element.EnumerateObject())
                {
                    queu.Enqueue(($"{parentPath}{nextEl.Name}", nextEl.Value));
                }
                break;
            case JsonValueKind.Array:
                foreach (var (nextEl, i) in element.EnumerateArray().Select((jsonElement, i) => (jsonElement, i)))
                {
                    queu.Enqueue(($"{parentPath}[{i}]", nextEl));
                }
                break;
            case JsonValueKind.Undefined:
            case JsonValueKind.String:
            case JsonValueKind.Number:
            case JsonValueKind.True:
            case JsonValueKind.False:
            case JsonValueKind.Null:
                yield return parentPath;
                break;
            default:
                throw new ArgumentOutOfRangeException();
        }
    }
}

并使用:

var json = ...;
using var doc = JsonDocument.Parse(json);
var names = EnumeratePaths(doc.RootElement).ToList();