| | | 1 | | using System.Dynamic; |
| | | 2 | | using System.Text.Json; |
| | | 3 | | using System.Text.Json.Serialization; |
| | | 4 | | |
| | | 5 | | namespace Elsa.Workflows.Serialization.Converters; |
| | | 6 | | |
| | | 7 | | /// <summary> |
| | | 8 | | /// Parses a JON string into a dynamic <see cref="ExpandoObject"/>. |
| | | 9 | | /// </summary> |
| | | 10 | | public sealed class ExpandoObjectConverter : JsonConverter<object> |
| | | 11 | | { |
| | | 12 | | /// <inheritdoc /> |
| | | 13 | | public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) |
| | | 14 | | { |
| | 0 | 15 | | JsonSerializer.Serialize(writer, value, value.GetType(), options); |
| | 0 | 16 | | } |
| | | 17 | | |
| | | 18 | | /// <inheritdoc /> |
| | | 19 | | public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
| | | 20 | | { |
| | 12 | 21 | | switch (reader.TokenType) |
| | | 22 | | { |
| | | 23 | | case JsonTokenType.Null: |
| | 0 | 24 | | return null!; |
| | | 25 | | case JsonTokenType.False: |
| | 0 | 26 | | return false; |
| | | 27 | | case JsonTokenType.True: |
| | 2 | 28 | | return true; |
| | | 29 | | case JsonTokenType.String: |
| | 2 | 30 | | return reader.GetString()!; |
| | | 31 | | case JsonTokenType.Number: |
| | | 32 | | { |
| | 2 | 33 | | if (reader.TryGetInt32(out var i)) |
| | 2 | 34 | | return i; |
| | 0 | 35 | | if (reader.TryGetInt64(out var l)) |
| | 0 | 36 | | return l; |
| | | 37 | | // BigInteger could be added here. |
| | | 38 | | |
| | 0 | 39 | | if (reader.TryGetDouble(out var d)) |
| | 0 | 40 | | return d; |
| | 0 | 41 | | using var doc = JsonDocument.ParseValue(ref reader); |
| | 0 | 42 | | return doc.RootElement.Clone(); |
| | | 43 | | } |
| | | 44 | | case JsonTokenType.StartArray: |
| | | 45 | | { |
| | 0 | 46 | | var list = new List<object>(); |
| | 0 | 47 | | while (reader.Read()) |
| | | 48 | | { |
| | 0 | 49 | | switch (reader.TokenType) |
| | | 50 | | { |
| | | 51 | | default: |
| | 0 | 52 | | list.Add(Read(ref reader, typeof(object), options)); |
| | 0 | 53 | | break; |
| | | 54 | | case JsonTokenType.EndArray: |
| | 0 | 55 | | return list.ToArray(); |
| | | 56 | | } |
| | | 57 | | } |
| | | 58 | | |
| | 0 | 59 | | throw new JsonException(); |
| | | 60 | | } |
| | | 61 | | case JsonTokenType.StartObject: |
| | 6 | 62 | | var dict = CreateDictionary(); |
| | 12 | 63 | | while (reader.Read()) |
| | | 64 | | { |
| | 12 | 65 | | switch (reader.TokenType) |
| | | 66 | | { |
| | | 67 | | case JsonTokenType.EndObject: |
| | 6 | 68 | | return dict; |
| | | 69 | | case JsonTokenType.PropertyName: |
| | 6 | 70 | | var key = reader.GetString()!; |
| | 6 | 71 | | reader.Read(); |
| | 6 | 72 | | var value = Read(ref reader, typeof(object), options)!; |
| | 6 | 73 | | dict.Add(key, value); |
| | 6 | 74 | | break; |
| | | 75 | | default: |
| | 0 | 76 | | throw new JsonException(); |
| | | 77 | | } |
| | | 78 | | } |
| | | 79 | | |
| | 0 | 80 | | throw new JsonException(); |
| | | 81 | | default: |
| | 0 | 82 | | throw new JsonException($"Unknown token {reader.TokenType}"); |
| | | 83 | | } |
| | 0 | 84 | | } |
| | | 85 | | |
| | 6 | 86 | | private IDictionary<string, object> CreateDictionary() => new ExpandoObject()!; |
| | | 87 | | } |