I need to be able to apply Math.Round to every Number in a JSON document. I don't have any control over the original writer of the JSON document so my input is a string. The numbers can be within JSON objects themselves which in turn could be within JsonArray so ideally I'd like to do it recursively.
I have tried to knock up something recursive but find I am struggling with JsonElement vs JsonProperty when diving down through the JSON so have resorted to only supporting the first tier of objects in the tree. Here is my (non recursive) code that only works on objects:
public static string ApplyRounding(string originalJson)
{
using var ms = new MemoryStream();
using var writer = new Utf8JsonWriter(ms, new JsonWriterOptions{ Indented = false, SkipValidation = true});
using var jsonDocument = JsonDocument.Parse(originalJson);
var root = jsonDocument.RootElement;
if (root.ValueKind == JsonValueKind.Object)
{
writer.WriteStartObject();
}
else
{
return string.Empty;
}
foreach (var property in root.EnumerateObject())
{
if (property.Value.ValueKind == JsonValueKind.Object)
{
writer.WritePropertyName(property.Name);
writer.WriteStartObject();
foreach (var innerProperty in property.Value.EnumerateObject())
{
if (innerProperty.Value.ValueKind == JsonValueKind.Number)
{
writer.WriteRoundedNumber(innerProperty, 15);
}
else
{
innerProperty.WriteTo(writer);
}
}
writer.WriteEndObject();
}
else if (property.Value.ValueKind == JsonValueKind.Number)
{
writer.WriteRoundedNumber(property, 15);
}
else
{
property.WriteTo(writer);
}
}
writer.WriteEndObject();
writer.Flush();
return Encoding.UTF8.GetString(ms.ToArray());
}
I am using C# 7 so am aware of the JsonNode type supporting in place editing of JSON but couldn't find a nice way to navigate that. I feel that this should be easier than it is, have I missed something?