This is a .NET Standard 2.0 library providing a lightweight dynamic wrapper for super-neat, fast and low-allocating working with JSON, based on the new System.Text.Json.
This library is especially useful for prototyping and scripting when you have to keep the code as clean and easy-to-read as possible.
PM> Install-Package Dynamic.Json
// parse json from string/stream/etc, for examplevarjson=DJson.Parse(@"{ ""versionNumber"": 1, ""product_name"": ""qwerty"", ""items"": [ 1, 2, 3 ], ""settings"": { ""enabled"": false }}");// or read json from filevarjson=DJson.Read("file.json");// or get json from HTTPvarjson=awaitDJson.GetAsync("https://api.com/endpoint");// or use HttpClient extensionvarjson=awaithttpClient.GetJsonAsync("https://api.com/endpoint");You can access json props either like class properties (json.someProperty) or like dictionary elements (json["someProperty"]). Both methods are identical, however, the first one looks better :)
intversion=json.versionNumber;stringname=json.product_name;intitem=json.items[1];intlength=json.items.length;//or json.items.count, as you preferboolenabled=json.settings.enabled;camelCase and snake_case are common naming styles in JSON, but uncommon in C# where we use PascalCase for public properties. Therefore, for perfectionists like me DJson allows to access json props not only by their original names (e.g. json.ip_endpoint), but also by its PascalCase version (e.g. json.IPEndpoint). DJson will try to resolve names automatically.
varval=json.VersionNumber;varstr=json.ProductName;vararr=json.Items[1];varlen=json.Items.Length;//or .Countvarobj=json.Settings.Enabled;You can enumerate json arrays in foreach or by implicit conversion to IEnumerable<dynamic>.
foreach(variteminjson.Items)Console.WriteLine($"{item}");varitems=(IEnumerable<dynamic>)json.Items;varsum=items.Where(x =>x>1).Sum(x =>x);You can enumerate json object props (string Name, dynamic Value) in foreach or by implicit conversion to IEnumerable<dynamic>.
foreach(varpropinjson.Settings)Console.WriteLine($"{prop.Name}: {prop.Value}");varprops=(IEnumerable<dynamic>)json.Settings;varnames=props.Where(x =>!x.Value).Select(x =>x.Name);While conversion to all built-in C# types is pretty transparent, you can also serialize json to any other type using implicit conversion.
varlist=(List<int>)json.Items;// dynamic array -> List<int>varsettings=(MyClass)json.Settings;// dynamic object -> MyClassvarobj=(AnotherType)json;People often use Unix time format in JSON and that's quite annoying to convert it to DateTime, so DJson does this for you automatically.
varjson=DJson.Parse(@"{ ""time"": ""2020-09-23T21:12:16Z"", ""unix_time"": 1600895536, ""unix_time_ms"": 1600895536123}");DateTimetime=json.Time;DateTimeunixTime=json.UnixTime;// DJson automatically detects if it's Unix time in secondsDateTimeunixTimeMs=json.UnixTimeMs;// or if it's Unix time in millisecondsOne can think that using dynamic wrapper brings a huge overhead, but it's actually not. Here is a simple benchmark, comparing DJson with JsonDocument from System.Text.Json and JToken from Newtonsoft.Json:
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated |
|--------------- |---------:|----------:|----------:|------:|--------:|-------:|----------:|
| SystemTextJson | 3.046 us | 0.0590 us | 0.0655 us | 1.00 | 0.00 | 0.1945 | 1.21 KB |
| DJson | 4.111 us | 0.0308 us | 0.0257 us | 1.35 | 0.03 | 0.5722 | 3.53 KB |
| Newtonsoft | 7.003 us | 0.1357 us | 0.1946 us | 2.29 | 0.09 | 1.4496 | 8.91 KB |
Of course, using .Deserialize<T>() would be even faster, but we're only talking about dynamic-like access, when you will likely spend a lot more time describing the types do deserialize your JSON to.
Feel free to create issues, feature requests and pull requests.
Cheers 🍻