FilterRule_SystemTextJson.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. using System;
  2. using System.Diagnostics.CodeAnalysis;
  3. using System.Linq;
  4. using System.Text.Json;
  5. using System.Text.Json.Serialization;
  6. using System.Text.Unicode;
  7. using Vit.Linq.MoreFilter;
  8. namespace Vit.Linq.QueryBuilder.SystemTextJson
  9. {
  10. /// <summary>
  11. /// This class is used to define a hierarchical filter for a given collection. This type can be serialized/deserialized by JSON.NET without needing to modify the data structure from QueryBuilder.
  12. /// </summary>
  13. [ExcludeFromCodeCoverage]
  14. public class FilterRule_SystemTextJson : FilterRuleWithMethod<FilterRule_SystemTextJson>
  15. {
  16. protected override object GetPrimitiveValue(Object value)
  17. {
  18. if (value is JsonElement je)
  19. {
  20. return GetPrimitiveValueFromJson(je);
  21. }
  22. return value;
  23. }
  24. public static FilterRule_SystemTextJson FromString(string filter)
  25. {
  26. return JsonSerializer.Deserialize<FilterRule_SystemTextJson>(filter, options);
  27. }
  28. static readonly JsonSerializerOptions options = GetDefaultOptions();
  29. public static JsonSerializerOptions GetDefaultOptions()
  30. {
  31. var options = new JsonSerializerOptions
  32. {
  33. // avoid transfer chinese character, for example {"title":"\u4ee3\u7801\u6539\u53d8\u4e16\u754c"}
  34. Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(UnicodeRanges.All),
  35. IncludeFields = true,
  36. DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
  37. };
  38. options.Converters.Add(new CustomObjectConverter());
  39. return options;
  40. }
  41. public static object GetPrimitiveValueFromJson(JsonElement value)
  42. {
  43. switch (value.ValueKind)
  44. {
  45. case JsonValueKind.Null: return null;
  46. case JsonValueKind.Undefined: return null;
  47. case JsonValueKind.True: return true;
  48. case JsonValueKind.False: return false;
  49. case JsonValueKind.Number: return value.GetDecimal();
  50. case JsonValueKind.String: return value.GetString();
  51. case JsonValueKind.Array:
  52. return value.EnumerateArray().Select(GetPrimitiveValueFromJson).ToList();
  53. }
  54. return value;
  55. }
  56. class CustomObjectConverter : JsonConverter<object>
  57. {
  58. public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
  59. {
  60. switch (reader.TokenType)
  61. {
  62. case JsonTokenType.Number:
  63. if (reader.TryGetInt32(out int intValue))
  64. {
  65. return intValue;
  66. }
  67. if (reader.TryGetDouble(out double doubleValue))
  68. {
  69. return doubleValue;
  70. }
  71. break;
  72. case JsonTokenType.True:
  73. return true;
  74. case JsonTokenType.False:
  75. return false;
  76. case JsonTokenType.String:
  77. return reader.GetString();
  78. case JsonTokenType.Null:
  79. return null;
  80. }
  81. using (JsonDocument doc = JsonDocument.ParseValue(ref reader))
  82. {
  83. return doc.RootElement.Clone();
  84. }
  85. }
  86. public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
  87. {
  88. JsonSerializer.Serialize(writer, value, value.GetType(), options);
  89. }
  90. }
  91. }
  92. }