using System; using System.Collections.Generic; using System.Globalization; using System.Text.Json; namespace MonoGame.Extended.Serialization.Json; /// /// Provides extension methods for working with . /// public static class Utf8JsonReaderExtensions { private static readonly Dictionary> s_stringParsers = new Dictionary> { {typeof(int), s => int.Parse(s, CultureInfo.InvariantCulture.NumberFormat)}, {typeof(float), s => float.Parse(s, CultureInfo.InvariantCulture.NumberFormat)}, {typeof(HslColor), s => HslColor.FromRgb(ColorExtensions.FromHex(s))} }; /// /// Reads a multi-dimensional JSON array and converts it to an array of the specified type. /// /// The type of the array elements. /// The to read from. /// An object that specifies serialization options to use. /// An array of the specified type. /// Thrown when the token type is not supported. public static T[] ReadAsMultiDimensional(this ref Utf8JsonReader reader, JsonSerializerOptions options) { var tokenType = reader.TokenType; switch (tokenType) { case JsonTokenType.StartArray: return reader.ReadAsJArray(options); case JsonTokenType.String: return reader.ReadAsDelimitedString(); case JsonTokenType.Number: return reader.ReadAsSingleValue(options); default: throw new NotSupportedException($"{tokenType} is not currently supported in the multi-dimensional parser"); } } private static T[] ReadAsSingleValue(this ref Utf8JsonReader reader, JsonSerializerOptions options) { var token = JsonDocument.ParseValue(ref reader).RootElement; var value = JsonSerializer.Deserialize(token.GetRawText(), options); return new T[] { value }; } private static T[] ReadAsJArray(this ref Utf8JsonReader reader, JsonSerializerOptions options) { var items = new List(); while (reader.Read() && reader.TokenType != JsonTokenType.EndArray) { if (reader.TokenType == JsonTokenType.EndArray) { break; } items.Add(JsonSerializer.Deserialize(ref reader, options)); } return items.ToArray(); } private static T[] ReadAsDelimitedString(this ref Utf8JsonReader reader) { var value = reader.GetString(); if (string.IsNullOrEmpty(value)) { return Array.Empty(); } Span values = value.Split(' '); var result = new T[values.Length]; var parser = s_stringParsers[typeof(T)]; for (int i = 0; i < values.Length; i++) { result[i] = (T)parser(values[i]); } return result; } }