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

Time:12-31

I wrote the following method to get all combinations of Path Type for all keys in a JSON by JSON.NET:

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;
}

I need a combination of Path Type for all elements of a JSON.

Can anyone help me to get the same result (or similar) with System.Text.Json?

Sample:

{
    "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 Result:

$-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

CodePudding user response:

You can use JsonDocument API which allows to parse and manipulate json in somewhat similar way to the Newtonsoft's one. Something like this (will need a little bit of work to fully represent needed format):

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();
        }
    }
}

And use:

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