Reputation: 733
I need to iterate through an JsonDocument and perform some sort of check depending on the JsonValueKind
I encounter.
I tried to do this validation check in such manner:
public bool Dec(JsonElement Element)
{
var ElementEnumeratable = Element.EnumerateObject();
foreach (var Elm in ElementEnumeratable )
{
string name = Elm.Name;
switch (Elm.Value.ValueKind)
{
case JsonValueKind.Array:
var jArray = Elm.Value;
return Dec(jArray);
case JsonValueKind.String:
string jString = Elm.Value.GetString();
break;
case JsonValueKind.Number:
int jNumber = Elm.Value.GetInt32();
break;
}
}
return true;
}
Problem here is when Elm
has ValueKind
array - I cannot pass it to the Dec
it seems like JsonElement
which has valuekind as array, cannot be converted into an EnumerateObject
?
What to do here?
Upvotes: 7
Views: 5789
Reputation: 5380
As I understand, if ValueKind
is JsonValueKind.Array
then you need to iterate array by using EnumerateArray()
so that you will have JsonElement
and call Dec
foreach element to validate each of them, like this:
public static bool Dec(JsonElement Element)
{
var ElementEnumeratable = Element.EnumerateObject();
foreach (var Elm in ElementEnumeratable)
{
string name = Elm.Name;
switch (Elm.Value.ValueKind)
{
case JsonValueKind.Array:
var jArray = Elm.Value;
foreach (var item in jArray.EnumerateArray())
{
Dec(item);
}
break;
case JsonValueKind.String:
string jString = Elm.Value.GetString();
break;
case JsonValueKind.Number:
int jNumber = Elm.Value.GetInt32();
break;
}
}
return true;
}
Upvotes: 7
Reputation: 31
I updated the proposed code this way:
public static JsonData Decode(JsonElement jsonElement, string elementName = "Root", JsonData parent = null)
{
JsonData result = null;
string jsonString = null;
double jsonDouble = 0;
bool jsonBool = false;
JsonElement jsonArray;
result = new JsonData(elementName, parent);
switch (jsonElement.ValueKind)
{
case JsonValueKind.Undefined:
break;
case JsonValueKind.Object:
ObjectEnumerator objectEnumerator = jsonElement.EnumerateObject();
foreach (var item in objectEnumerator)
{
string name = item.Name;
switch (item.Value.ValueKind)
{
case JsonValueKind.Undefined:
break;
case JsonValueKind.Object:
JsonElement element = (JsonElement)item.Value;
result.Childrens.Add(Decode(element, name, result));
break;
case JsonValueKind.Array:
jsonArray = item.Value;
foreach (var arrayItem in jsonArray.EnumerateArray())
{
result.Childrens.Add(Decode(arrayItem, name, result));
}
break;
case JsonValueKind.String:
jsonString = item.Value.GetString();
result.Items.Add(name, jsonString);
break;
case JsonValueKind.Number:
jsonDouble = item.Value.GetDouble();
result.Items.Add(name, jsonDouble);
break;
case JsonValueKind.True:
jsonBool = item.Value.GetBoolean();
result.Items.Add(name, jsonBool);
break;
case JsonValueKind.False:
jsonBool = item.Value.GetBoolean();
result.Items.Add(name, jsonBool);
break;
case JsonValueKind.Null:
result.Items.Add(name, null);
break;
default:
break;
}
}
break;
case JsonValueKind.Array:
jsonArray = jsonElement;
foreach (var arrayItem in jsonArray.EnumerateArray())
{
result.Items.Add(elementName, arrayItem);
}
break;
case JsonValueKind.String:
jsonString = jsonElement.GetString();
result.Items.Add(elementName, jsonString);
break;
case JsonValueKind.Number:
jsonDouble = jsonElement.GetDouble();
result.Items.Add(elementName, jsonDouble);
break;
case JsonValueKind.True:
jsonBool = jsonElement.GetBoolean();
result.Items.Add(elementName, jsonBool);
break;
case JsonValueKind.False:
jsonBool = jsonElement.GetBoolean();
result.Items.Add(elementName, jsonBool);
break;
case JsonValueKind.Null:
result.Items.Add(elementName, null);
break;
default:
break;
}
return result;
}
Returned class is the following one:
public class JsonData
{
public JsonData Parent { get; private set; }
public List<JsonData> Childrens { get; private set; }
public string Name { get; private set; }
public Dictionary<string, object> Items { get; private set; }
public JsonData(string name, JsonData parent = null)
{
Parent = parent;
Childrens = new List<JsonData>();
Name = name;
Items = new Dictionary<string, object>();
}
}
Usage:
JsonDocument jsonDoc = null;
JsonData jsonData = null;
string json = File.ReadAllText(@"c:\jsonpath.json");
if (!string.IsNullOrEmpty(json))
{
jsonDoc = JsonDocument.Parse(json, new JsonDocumentOptions { CommentHandling = JsonCommentHandling.Skip });
if (jsonDoc != null)
{
jsonData = Decode(jsonDoc.RootElement);
}
}
if (jsonData != null)
{
JsonData financialData = jsonData.Childrens.FirstOrDefault(c => c.Name == "Financial Data");
if (financialData != null)
{
List<JsonData> transactions = financialData.Childrens.Where(c => c.Name == "Transaction history").ToList<JsonData>();
}
}
Upvotes: 2
Reputation: 613
I think you're doing the switch in the wrong place. If Dec()
is called with an Array, it will still call EnumerateObject()
. It would need to call EnumerateArray()
for an array.
Upvotes: 0