System.Text.Json generally covers all cases, however, if you don't want to declare deserialization models, or don't want to declare JsonSerializerContext for AOT app, or json object varies, then this json parser may help. It deserializes json to Dictionary<string, object>, or List, or object with primitive type. Nested objects are also dictionaries and so the arrays. AOT friendly, properties access by a path.
Add JsonParser.cs to your project and reference AleProjects.Json namespace in your code.
using AleProjects.Json;
...
string json = @"{
""User"": { ""Name"": ""Leo"", ""Role"": ""Admin"", ""Enabled"": true, ""LastLogon"": "2026-08-14T14:30:00-04:00"},
""Array1"": [0, 1, 2, 3, 4, 5], // this is comment
""Array2"": [0, 1, 2.1, 3.112, 0.342],
/*
This is another comment
*/
""Array3"": [""\/Date(1614929892344)\/""],
""Array4"": [""\/Date(1614929892344)\/"", ""QWERTY""],
""Array5"": [ { ""x"": 1, ""y"": 2 }, { ""x"": 3, ""y"": 4 } ]
""IntValue"": 1,
""LongValue"": 8589934592,
""DoubleValue"": 3.1416,
""BoolValue"": true,
""NullValue"": null,
""DateTimeAlt"": ""2009-06-15T13:45:30.000Z""
}";
JsonDoc doc;
try
{
doc = JsonDoc.Parse(json, new JsonDoc.ParsingSettings() { AllowComments = true, RecognizeDateTime = true, ForceDoubleInArrays = false, StrictPropertyNames = true });
}
catch (JsonParseException ex)
{
System.Diagnostics.Debug.WriteLine("Error message: {0}, code {1}, line {2}, position {3}", ex.Message, ex.Data["Code"], ex.Data["Line"], ex.Data["Position"]);
}
catch
{
}
if (doc.Root is JsonDoc.JsonObject root)
{
// access properties by path
var userName = root.GetValueOrDefault<string>("User", "Name");
var lastLogon = root.GetValueOrDefault<DateTimeOffset>("User", "LastLogon");
var x = root.GetValueOrDefault<int>("Array5", "1", "x"); // x will be 3
var array1 = root.GetValueOrDefault<IList<int>>("Array1");
var array2 = root.GetValueOrDefault<IList<double>>("Array2");
var array3 = root.GetValueOrDefault<IList<DateTimeOffset>>("Array3");
var array4 = root.GetValueOrDefault<IList<object>>("Array4");
array3.Add(DateTimeOffset.Now); // parsed object is not immutable and can be modified
}
To be continued ...