Utf8JsonReaderExtensions.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Text.Json;
  5. namespace MonoGame.Extended.Serialization.Json;
  6. /// <summary>
  7. /// Provides extension methods for working with <see cref="Utf8JsonReader"/>.
  8. /// </summary>
  9. public static class Utf8JsonReaderExtensions
  10. {
  11. private static readonly Dictionary<Type, Func<string, object>> s_stringParsers = new Dictionary<Type, Func<string, object>>
  12. {
  13. {typeof(int), s => int.Parse(s, CultureInfo.InvariantCulture.NumberFormat)},
  14. {typeof(float), s => float.Parse(s, CultureInfo.InvariantCulture.NumberFormat)},
  15. {typeof(HslColor), s => HslColor.FromRgb(ColorExtensions.FromHex(s))}
  16. };
  17. /// <summary>
  18. /// Reads a multi-dimensional JSON array and converts it to an array of the specified type.
  19. /// </summary>
  20. /// <typeparam name="T">The type of the array elements.</typeparam>
  21. /// <param name="reader">The <see cref="Utf8JsonReader"/> to read from.</param>
  22. /// <param name="options">An object that specifies serialization options to use.</param>
  23. /// <returns>An array of the specified type.</returns>
  24. /// <exception cref="NotSupportedException">Thrown when the token type is not supported.</exception>
  25. public static T[] ReadAsMultiDimensional<T>(this ref Utf8JsonReader reader, JsonSerializerOptions options)
  26. {
  27. var tokenType = reader.TokenType;
  28. switch (tokenType)
  29. {
  30. case JsonTokenType.StartArray:
  31. return reader.ReadAsJArray<T>(options);
  32. case JsonTokenType.String:
  33. return reader.ReadAsDelimitedString<T>();
  34. case JsonTokenType.Number:
  35. return reader.ReadAsSingleValue<T>(options);
  36. default:
  37. throw new NotSupportedException($"{tokenType} is not currently supported in the multi-dimensional parser");
  38. }
  39. }
  40. private static T[] ReadAsSingleValue<T>(this ref Utf8JsonReader reader, JsonSerializerOptions options)
  41. {
  42. var token = JsonDocument.ParseValue(ref reader).RootElement;
  43. var value = JsonSerializer.Deserialize<T>(token.GetRawText(), options);
  44. return new T[] { value };
  45. }
  46. private static T[] ReadAsJArray<T>(this ref Utf8JsonReader reader, JsonSerializerOptions options)
  47. {
  48. var items = new List<T>();
  49. while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
  50. {
  51. if (reader.TokenType == JsonTokenType.EndArray)
  52. {
  53. break;
  54. }
  55. items.Add(JsonSerializer.Deserialize<T>(ref reader, options));
  56. }
  57. return items.ToArray();
  58. }
  59. private static T[] ReadAsDelimitedString<T>(this ref Utf8JsonReader reader)
  60. {
  61. var value = reader.GetString();
  62. if (string.IsNullOrEmpty(value))
  63. {
  64. return Array.Empty<T>();
  65. }
  66. Span<string> values = value.Split(' ');
  67. var result = new T[values.Length];
  68. var parser = s_stringParsers[typeof(T)];
  69. for (int i = 0; i < values.Length; i++)
  70. {
  71. result[i] = (T)parser(values[i]);
  72. }
  73. return result;
  74. }
  75. }