Move over to JsonElement

This commit is contained in:
Daniel Cronqvist 2024-08-08 23:55:26 +02:00
parent 2a10ebb496
commit 5626614acd
3 changed files with 291 additions and 219 deletions

View file

@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text.Json;
namespace DotTiled;
internal static class ExtensionsJsonElement
{
internal static T GetRequiredProperty<T>(this JsonElement element, string propertyName)
{
if (!element.TryGetProperty(propertyName, out var property))
throw new JsonException($"Missing required property '{propertyName}'.");
return property.GetValueAs<T>();
}
internal static T GetOptionalProperty<T>(this JsonElement element, string propertyName, T defaultValue)
{
if (!element.TryGetProperty(propertyName, out var property))
return defaultValue;
return property.GetValueAs<T>();
}
internal static T GetValueAs<T>(this JsonElement element)
{
string val = typeof(T) switch
{
Type t when t == typeof(string) => element.GetString()!,
Type t when t == typeof(int) => element.GetInt32().ToString(CultureInfo.InvariantCulture),
Type t when t == typeof(uint) => element.GetUInt32().ToString(CultureInfo.InvariantCulture),
Type t when t == typeof(float) => element.GetSingle().ToString(CultureInfo.InvariantCulture),
_ => throw new JsonException($"Unsupported type '{typeof(T)}'.")
};
return (T)Convert.ChangeType(val, typeof(T), CultureInfo.InvariantCulture);
}
internal static T GetRequiredPropertyParseable<T>(this JsonElement element, string propertyName) where T : IParsable<T>
{
if (!element.TryGetProperty(propertyName, out var property))
throw new JsonException($"Missing required property '{propertyName}'.");
return T.Parse(property.GetString()!, CultureInfo.InvariantCulture);
}
internal static T GetRequiredPropertyParseable<T>(this JsonElement element, string propertyName, Func<string, T> parser)
{
if (!element.TryGetProperty(propertyName, out var property))
throw new JsonException($"Missing required property '{propertyName}'.");
return parser(property.GetString()!);
}
internal static T GetOptionalPropertyParseable<T>(this JsonElement element, string propertyName, T defaultValue) where T : IParsable<T>
{
if (!element.TryGetProperty(propertyName, out var property))
return defaultValue;
return T.Parse(property.GetString()!, CultureInfo.InvariantCulture);
}
internal static T GetOptionalPropertyParseable<T>(this JsonElement element, string propertyName, Func<string, T> parser, T defaultValue)
{
if (!element.TryGetProperty(propertyName, out var property))
return defaultValue;
return parser(property.GetString()!);
}
internal static T GetRequiredPropertyCustom<T>(this JsonElement element, string propertyName, Func<JsonElement, T> parser)
{
if (!element.TryGetProperty(propertyName, out var property))
throw new JsonException($"Missing required property '{propertyName}'.");
return parser(property);
}
internal static T GetOptionalPropertyCustom<T>(this JsonElement element, string propertyName, Func<JsonElement, T> parser, T defaultValue)
{
if (!element.TryGetProperty(propertyName, out var property))
return defaultValue;
return parser(property);
}
internal static List<T> GetValueAsList<T>(this JsonElement element, Func<JsonElement, T> parser)
{
var list = new List<T>();
foreach (var item in element.EnumerateArray())
list.Add(parser(item));
return list;
}
}

View file

@ -7,83 +7,58 @@ namespace DotTiled;
internal partial class Tmj internal partial class Tmj
{ {
internal static Map ReadMap(ref Utf8JsonReader reader) internal static Map ReadMap(JsonElement element)
{ {
string version = default!; var version = element.GetRequiredProperty<string>("version");
string tiledVersion = default!; var tiledVersion = element.GetRequiredProperty<string>("tiledversion");
string @class = ""; string @class = element.GetOptionalProperty<string>("class", "");
MapOrientation orientation = default; var orientation = element.GetRequiredPropertyParseable<MapOrientation>("orientation", s => s switch
RenderOrder renderOrder = RenderOrder.RightDown;
int compressionLevel = -1;
uint width = 0;
uint height = 0;
uint tileWidth = 0;
uint tileHeight = 0;
uint? hexSideLength = null;
StaggerAxis? staggerAxis = null;
StaggerIndex? staggerIndex = null;
float parallaxOriginX = 0.0f;
float parallaxOriginY = 0.0f;
Color backgroundColor = Color.Parse("#00000000", CultureInfo.InvariantCulture);
uint nextLayerID = 0;
uint nextObjectID = 0;
bool infinite = false;
// At most one of
Dictionary<string, IProperty>? properties = null;
// Any number of
List<BaseLayer> layers = [];
List<Tileset> tilesets = [];
reader.ProcessJsonObject([
new RequiredProperty("version", (ref Utf8JsonReader reader) => version = reader.Progress(reader.GetString()!)),
new RequiredProperty("tiledversion", (ref Utf8JsonReader reader) => tiledVersion = reader.Progress(reader.GetString()!)),
new OptionalProperty("class", (ref Utf8JsonReader reader) => @class = reader.Progress(reader.GetString() ?? ""), allowNull: true),
new RequiredProperty("orientation", (ref Utf8JsonReader reader) => orientation = reader.Progress(reader.GetString()) switch
{ {
"orthogonal" => MapOrientation.Orthogonal, "orthogonal" => MapOrientation.Orthogonal,
"isometric" => MapOrientation.Isometric, "isometric" => MapOrientation.Isometric,
"staggered" => MapOrientation.Staggered, "staggered" => MapOrientation.Staggered,
"hexagonal" => MapOrientation.Hexagonal, "hexagonal" => MapOrientation.Hexagonal,
_ => throw new JsonException("Invalid orientation.") _ => throw new JsonException($"Unknown orientation '{s}'")
}), });
new OptionalProperty("renderorder", (ref Utf8JsonReader reader) => renderOrder = reader.Progress(reader.GetString()) switch var renderOrder = element.GetOptionalPropertyParseable<RenderOrder>("renderorder", s => s switch
{ {
"right-down" => RenderOrder.RightDown, "right-down" => RenderOrder.RightDown,
"right-up" => RenderOrder.RightUp, "right-up" => RenderOrder.RightUp,
"left-down" => RenderOrder.LeftDown, "left-down" => RenderOrder.LeftDown,
"left-up" => RenderOrder.LeftUp, "left-up" => RenderOrder.LeftUp,
_ => throw new JsonException("Invalid render order.") _ => throw new JsonException($"Unknown render order '{s}'")
}), }, RenderOrder.RightDown);
new OptionalProperty("compressionlevel", (ref Utf8JsonReader reader) => compressionLevel = reader.Progress(reader.GetInt32())), var compressionLevel = element.GetOptionalProperty<int>("compressionlevel", -1);
new RequiredProperty("width", (ref Utf8JsonReader reader) => width = reader.Progress(reader.GetUInt32())), var width = element.GetRequiredProperty<uint>("width");
new RequiredProperty("height", (ref Utf8JsonReader reader) => height = reader.Progress(reader.GetUInt32())), var height = element.GetRequiredProperty<uint>("height");
new RequiredProperty("tilewidth", (ref Utf8JsonReader reader) => tileWidth = reader.Progress(reader.GetUInt32())), var tileWidth = element.GetRequiredProperty<uint>("tilewidth");
new RequiredProperty("tileheight", (ref Utf8JsonReader reader) => tileHeight = reader.Progress(reader.GetUInt32())), var tileHeight = element.GetRequiredProperty<uint>("tileheight");
new OptionalProperty("hexsidelength", (ref Utf8JsonReader reader) => hexSideLength = reader.Progress(reader.GetUInt32())), var hexSideLength = element.GetOptionalProperty<uint?>("hexsidelength", null);
new OptionalProperty("staggeraxis", (ref Utf8JsonReader reader) => staggerAxis = reader.Progress(reader.GetString()) switch var staggerAxis = element.GetOptionalPropertyParseable<StaggerAxis?>("staggeraxis", s => s switch
{ {
"x" => StaggerAxis.X, "x" => StaggerAxis.X,
"y" => StaggerAxis.Y, "y" => StaggerAxis.Y,
_ => throw new JsonException("Invalid stagger axis.") _ => throw new JsonException($"Unknown stagger axis '{s}'")
}), }, null);
new OptionalProperty("staggerindex", (ref Utf8JsonReader reader) => staggerIndex = reader.Progress(reader.GetString()) switch var staggerIndex = element.GetOptionalPropertyParseable<StaggerIndex?>("staggerindex", s => s switch
{ {
"odd" => StaggerIndex.Odd, "odd" => StaggerIndex.Odd,
"even" => StaggerIndex.Even, "even" => StaggerIndex.Even,
_ => throw new JsonException("Invalid stagger index.") _ => throw new JsonException($"Unknown stagger index '{s}'")
}), }, null);
new OptionalProperty("parallaxoriginx", (ref Utf8JsonReader reader) => parallaxOriginX = reader.Progress(reader.GetSingle())), var parallaxOriginX = element.GetOptionalProperty<float>("parallaxoriginx", 0.0f);
new OptionalProperty("parallaxoriginy", (ref Utf8JsonReader reader) => parallaxOriginY = reader.Progress(reader.GetSingle())), var parallaxOriginY = element.GetOptionalProperty<float>("parallaxoriginy", 0.0f);
new OptionalProperty("backgroundcolor", (ref Utf8JsonReader reader) => backgroundColor = Color.Parse(reader.Progress(reader.GetString()!), CultureInfo.InvariantCulture)), var backgroundColor = element.GetOptionalPropertyParseable<Color>("backgroundcolor", s => Color.Parse(s, CultureInfo.InvariantCulture), Color.Parse("#00000000", CultureInfo.InvariantCulture));
new RequiredProperty("nextlayerid", (ref Utf8JsonReader reader) => nextLayerID = reader.Progress(reader.GetUInt32())), var nextLayerID = element.GetRequiredProperty<uint>("nextlayerid");
new RequiredProperty("nextobjectid", (ref Utf8JsonReader reader) => nextObjectID = reader.Progress(reader.GetUInt32())), var nextObjectID = element.GetRequiredProperty<uint>("nextobjectid");
new OptionalProperty("infinite", (ref Utf8JsonReader reader) => infinite = reader.Progress(reader.GetUInt32()) == 1), var infinite = element.GetOptionalProperty<int>("infinite", 0) == 1;
new OptionalProperty("properties", (ref Utf8JsonReader reader) => properties = ReadProperties(ref reader)), // At most one of
new OptionalProperty("tilesets", (ref Utf8JsonReader reader) => tilesets = ReadTilesets(ref reader)) Dictionary<string, IProperty>? properties = element.GetOptionalPropertyCustom<Dictionary<string, IProperty>>("properties", ReadProperties, null);
], "map");
// Any number of
List<BaseLayer> layers = [];
List<Tileset> tilesets = [];
return new Map return new Map
{ {
@ -112,168 +87,175 @@ internal partial class Tmj
}; };
} }
internal static Dictionary<string, IProperty> ReadProperties(ref Utf8JsonReader reader) internal static Dictionary<string, IProperty> ReadProperties(JsonElement element)
{ {
var properties = new Dictionary<string, IProperty>(); var properties = new Dictionary<string, IProperty>();
reader.ProcessJsonArray((ref Utf8JsonReader reader) => element.GetValueAsList<IProperty>(e =>
{ {
var property = ReadProperty(ref reader); var name = e.GetRequiredProperty<string>("name");
properties.Add(property.Name, property); var type = e.GetOptionalPropertyParseable<PropertyType>("type", s => s switch
}); {
"string" => PropertyType.String,
"int" => PropertyType.Int,
"float" => PropertyType.Float,
"bool" => PropertyType.Bool,
"color" => PropertyType.Color,
"file" => PropertyType.File,
"object" => PropertyType.Object,
"class" => PropertyType.Class,
_ => throw new JsonException("Invalid property type")
}, PropertyType.String);
IProperty property = type switch
{
PropertyType.String => new StringProperty { Name = name, Value = e.GetRequiredProperty<string>("value") },
PropertyType.Int => new IntProperty { Name = name, Value = e.GetRequiredProperty<int>("value") },
PropertyType.Float => new FloatProperty { Name = name, Value = e.GetRequiredProperty<float>("value") },
PropertyType.Bool => new BoolProperty { Name = name, Value = e.GetRequiredProperty<bool>("value") },
PropertyType.Color => new ColorProperty { Name = name, Value = e.GetRequiredPropertyParseable<Color>("value") },
PropertyType.File => new FileProperty { Name = name, Value = e.GetRequiredProperty<string>("value") },
PropertyType.Object => new ObjectProperty { Name = name, Value = e.GetRequiredProperty<uint>("value") },
PropertyType.Class => ReadClassProperty(e),
_ => throw new JsonException("Invalid property type")
};
return property!;
}).ForEach(p => properties.Add(p.Name, p));
return properties; return properties;
} }
internal static IProperty ReadProperty(ref Utf8JsonReader reader) internal static ClassProperty ReadClassProperty(JsonElement element)
{ {
string name = default!; var name = element.GetRequiredProperty<string>("name");
string type = default!; var propertyType = element.GetRequiredProperty<string>("propertytype");
IProperty property = null;
reader.ProcessJsonObject([ var properties = element.GetRequiredPropertyCustom<Dictionary<string, IProperty>>("properties", ReadProperties);
new RequiredProperty("name", (ref Utf8JsonReader reader) => name = reader.Progress(reader.GetString()!)),
new RequiredProperty("type", (ref Utf8JsonReader reader) => type = reader.Progress(reader.GetString()!)),
new RequiredProperty("value", (ref Utf8JsonReader reader) =>
{
property = type switch
{
"string" => new StringProperty { Name = name, Value = reader.Progress(reader.GetString()!) },
"int" => new IntProperty { Name = name, Value = reader.Progress(reader.GetInt32()) },
"float" => new FloatProperty { Name = name, Value = reader.Progress(reader.GetSingle()) },
"bool" => new BoolProperty { Name = name, Value = reader.Progress(reader.GetBoolean()) },
"color" => new ColorProperty { Name = name, Value = Color.Parse(reader.Progress(reader.GetString()!), CultureInfo.InvariantCulture) },
"file" => new FileProperty { Name = name, Value = reader.Progress(reader.GetString()!) },
"object" => new ObjectProperty { Name = name, Value = reader.Progress(reader.GetUInt32()) },
// "class" => ReadClassProperty(ref reader),
_ => throw new JsonException("Invalid property type.")
};
}),
], "property");
return property!; return new ClassProperty { Name = name, PropertyType = propertyType, Properties = properties };
} }
internal static List<Tileset> ReadTilesets(ref Utf8JsonReader reader) // internal static List<Tileset> ReadTilesets(ref Utf8JsonReader reader)
{ // {
var tilesets = new List<Tileset>(); // var tilesets = new List<Tileset>();
reader.ProcessJsonArray((ref Utf8JsonReader reader) => // reader.ProcessJsonArray((ref Utf8JsonReader reader) =>
{ // {
var tileset = ReadTileset(ref reader); // var tileset = ReadTileset(ref reader);
tilesets.Add(tileset); // tilesets.Add(tileset);
}); // });
return tilesets; // return tilesets;
} // }
internal static Tileset ReadTileset(ref Utf8JsonReader reader) // internal static Tileset ReadTileset(ref Utf8JsonReader reader)
{ // {
string? version = null; // string? version = null;
string? tiledVersion = null; // string? tiledVersion = null;
uint? firstGID = null; // uint? firstGID = null;
string? source = null; // string? source = null;
string? name = null; // string? name = null;
string @class = ""; // string @class = "";
uint? tileWidth = null; // uint? tileWidth = null;
uint? tileHeight = null; // uint? tileHeight = null;
uint? spacing = null; // uint? spacing = null;
uint? margin = null; // uint? margin = null;
uint? tileCount = null; // uint? tileCount = null;
uint? columns = null; // uint? columns = null;
ObjectAlignment objectAlignment = ObjectAlignment.Unspecified; // ObjectAlignment objectAlignment = ObjectAlignment.Unspecified;
FillMode fillMode = FillMode.Stretch; // FillMode fillMode = FillMode.Stretch;
string? image = null; // string? image = null;
uint? imageWidth = null; // uint? imageWidth = null;
uint? imageHeight = null; // uint? imageHeight = null;
Dictionary<string, IProperty>? properties = null; // Dictionary<string, IProperty>? properties = null;
reader.ProcessJsonObject([ // reader.ProcessJsonObject([
new OptionalProperty("version", (ref Utf8JsonReader reader) => version = reader.Progress(reader.GetString())), // new OptionalProperty("version", (ref Utf8JsonReader reader) => version = reader.Progress(reader.GetString())),
new OptionalProperty("tiledversion", (ref Utf8JsonReader reader) => tiledVersion = reader.Progress(reader.GetString())), // new OptionalProperty("tiledversion", (ref Utf8JsonReader reader) => tiledVersion = reader.Progress(reader.GetString())),
new OptionalProperty("firstgid", (ref Utf8JsonReader reader) => firstGID = reader.Progress(reader.GetUInt32())), // new OptionalProperty("firstgid", (ref Utf8JsonReader reader) => firstGID = reader.Progress(reader.GetUInt32())),
new OptionalProperty("source", (ref Utf8JsonReader reader) => source = reader.Progress(reader.GetString())), // new OptionalProperty("source", (ref Utf8JsonReader reader) => source = reader.Progress(reader.GetString())),
new OptionalProperty("name", (ref Utf8JsonReader reader) => name = reader.Progress(reader.GetString())), // new OptionalProperty("name", (ref Utf8JsonReader reader) => name = reader.Progress(reader.GetString())),
new OptionalProperty("class", (ref Utf8JsonReader reader) => @class = reader.Progress(reader.GetString() ?? ""), allowNull: true), // new OptionalProperty("class", (ref Utf8JsonReader reader) => @class = reader.Progress(reader.GetString() ?? ""), allowNull: true),
new OptionalProperty("tilewidth", (ref Utf8JsonReader reader) => tileWidth = reader.Progress(reader.GetUInt32())), // new OptionalProperty("tilewidth", (ref Utf8JsonReader reader) => tileWidth = reader.Progress(reader.GetUInt32())),
new OptionalProperty("tileheight", (ref Utf8JsonReader reader) => tileHeight = reader.Progress(reader.GetUInt32())), // new OptionalProperty("tileheight", (ref Utf8JsonReader reader) => tileHeight = reader.Progress(reader.GetUInt32())),
new OptionalProperty("spacing", (ref Utf8JsonReader reader) => spacing = reader.Progress(reader.GetUInt32())), // new OptionalProperty("spacing", (ref Utf8JsonReader reader) => spacing = reader.Progress(reader.GetUInt32())),
new OptionalProperty("margin", (ref Utf8JsonReader reader) => margin = reader.Progress(reader.GetUInt32())), // new OptionalProperty("margin", (ref Utf8JsonReader reader) => margin = reader.Progress(reader.GetUInt32())),
new OptionalProperty("tilecount", (ref Utf8JsonReader reader) => tileCount = reader.Progress(reader.GetUInt32())), // new OptionalProperty("tilecount", (ref Utf8JsonReader reader) => tileCount = reader.Progress(reader.GetUInt32())),
new OptionalProperty("columns", (ref Utf8JsonReader reader) => columns = reader.Progress(reader.GetUInt32())), // new OptionalProperty("columns", (ref Utf8JsonReader reader) => columns = reader.Progress(reader.GetUInt32())),
new OptionalProperty("objectalignment", (ref Utf8JsonReader reader) => objectAlignment = reader.Progress(reader.GetString()) switch // new OptionalProperty("objectalignment", (ref Utf8JsonReader reader) => objectAlignment = reader.Progress(reader.GetString()) switch
{ // {
"unspecified" => ObjectAlignment.Unspecified, // "unspecified" => ObjectAlignment.Unspecified,
"topleft" => ObjectAlignment.TopLeft, // "topleft" => ObjectAlignment.TopLeft,
"top" => ObjectAlignment.Top, // "top" => ObjectAlignment.Top,
"topright" => ObjectAlignment.TopRight, // "topright" => ObjectAlignment.TopRight,
"left" => ObjectAlignment.Left, // "left" => ObjectAlignment.Left,
"center" => ObjectAlignment.Center, // "center" => ObjectAlignment.Center,
"right" => ObjectAlignment.Right, // "right" => ObjectAlignment.Right,
"bottomleft" => ObjectAlignment.BottomLeft, // "bottomleft" => ObjectAlignment.BottomLeft,
"bottom" => ObjectAlignment.Bottom, // "bottom" => ObjectAlignment.Bottom,
"bottomright" => ObjectAlignment.BottomRight, // "bottomright" => ObjectAlignment.BottomRight,
_ => throw new JsonException("Invalid object alignment.") // _ => throw new JsonException("Invalid object alignment.")
}), // }),
new OptionalProperty("fillmode", (ref Utf8JsonReader reader) => fillMode = reader.Progress(reader.GetString()) switch // new OptionalProperty("fillmode", (ref Utf8JsonReader reader) => fillMode = reader.Progress(reader.GetString()) switch
{ // {
"stretch" => FillMode.Stretch, // "stretch" => FillMode.Stretch,
"preserve-aspect-fit" => FillMode.PreserveAspectFit, // "preserve-aspect-fit" => FillMode.PreserveAspectFit,
_ => throw new JsonException("Invalid fill mode.") // _ => throw new JsonException("Invalid fill mode.")
}), // }),
new OptionalProperty("image", (ref Utf8JsonReader reader) => image = reader.Progress(reader.GetString())), // new OptionalProperty("image", (ref Utf8JsonReader reader) => image = reader.Progress(reader.GetString())),
new OptionalProperty("imagewidth", (ref Utf8JsonReader reader) => imageWidth = reader.Progress(reader.GetUInt32())), // new OptionalProperty("imagewidth", (ref Utf8JsonReader reader) => imageWidth = reader.Progress(reader.GetUInt32())),
new OptionalProperty("imageheight", (ref Utf8JsonReader reader) => imageHeight = reader.Progress(reader.GetUInt32())), // new OptionalProperty("imageheight", (ref Utf8JsonReader reader) => imageHeight = reader.Progress(reader.GetUInt32())),
new OptionalProperty("properties", (ref Utf8JsonReader reader) => properties = ReadProperties(ref reader)) // new OptionalProperty("properties", (ref Utf8JsonReader reader) => properties = ReadProperties(ref reader))
], "tileset"); // ], "tileset");
Image? imageInstance = image is not null ? new Image // Image? imageInstance = image is not null ? new Image
{ // {
Format = ParseImageFormatFromSource(image), // Format = ParseImageFormatFromSource(image),
Width = imageWidth, // Width = imageWidth,
Height = imageHeight, // Height = imageHeight,
Source = image // Source = image
} : null; // } : null;
return new Tileset // return new Tileset
{ // {
Version = version, // Version = version,
TiledVersion = tiledVersion, // TiledVersion = tiledVersion,
FirstGID = firstGID, // FirstGID = firstGID,
Source = source, // Source = source,
Name = name, // Name = name,
Class = @class, // Class = @class,
TileWidth = tileWidth, // TileWidth = tileWidth,
TileHeight = tileHeight, // TileHeight = tileHeight,
Spacing = spacing, // Spacing = spacing,
Margin = margin, // Margin = margin,
TileCount = tileCount, // TileCount = tileCount,
Columns = columns, // Columns = columns,
ObjectAlignment = objectAlignment, // ObjectAlignment = objectAlignment,
FillMode = fillMode, // FillMode = fillMode,
Image = imageInstance, // Image = imageInstance,
Properties = properties // Properties = properties
}; // };
} // }
private static ImageFormat ParseImageFormatFromSource(string? source) // private static ImageFormat ParseImageFormatFromSource(string? source)
{ // {
if (source is null) // if (source is null)
throw new JsonException("Image source is required to determine image format."); // throw new JsonException("Image source is required to determine image format.");
var extension = Path.GetExtension(source); // var extension = Path.GetExtension(source);
return extension switch // return extension switch
{ // {
".png" => ImageFormat.Png, // ".png" => ImageFormat.Png,
".jpg" => ImageFormat.Jpg, // ".jpg" => ImageFormat.Jpg,
".jpeg" => ImageFormat.Jpg, // ".jpeg" => ImageFormat.Jpg,
".gif" => ImageFormat.Gif, // ".gif" => ImageFormat.Gif,
".bmp" => ImageFormat.Bmp, // ".bmp" => ImageFormat.Bmp,
_ => throw new JsonException("Invalid image format.") // _ => throw new JsonException("Invalid image format.")
}; // };
} // }
} }

View file

@ -17,16 +17,9 @@ public class TmjMapReader : IMapReader
public Map ReadMap() public Map ReadMap()
{ {
var bytes = Encoding.UTF8.GetBytes(_jsonString); var jsonDoc = JsonDocument.Parse(_jsonString);
var options = new JsonReaderOptions var rootElement = jsonDoc.RootElement;
{ return Tmj.ReadMap(rootElement);
AllowTrailingCommas = true,
CommentHandling = JsonCommentHandling.Skip,
};
var reader = new Utf8JsonReader(bytes, options);
reader.MoveToContent();
return Tmj.ReadMap(ref reader);
} }
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)