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