| | 1 | | // Copyright (c) Microsoft Corporation. All rights reserved. |
| | 2 | | // Licensed under the MIT License. |
| | 3 | |
|
| | 4 | | using System; |
| | 5 | | using System.Collections; |
| | 6 | | using System.Collections.Generic; |
| | 7 | | using System.Diagnostics; |
| | 8 | | using System.Dynamic; |
| | 9 | | using System.IO; |
| | 10 | | using System.Linq.Expressions; |
| | 11 | | using System.Reflection; |
| | 12 | | using System.Text; |
| | 13 | | using System.Text.Json; |
| | 14 | | using System.Threading; |
| | 15 | | using System.Threading.Tasks; |
| | 16 | | using Azure.Core.Serialization; |
| | 17 | |
|
| | 18 | | #pragma warning disable 1591 |
| | 19 | |
|
| | 20 | | namespace Azure.Core |
| | 21 | | { |
| | 22 | | /// <summary> |
| | 23 | | /// |
| | 24 | | /// </summary> |
| | 25 | | public class DynamicJson : IDynamicMetaObjectProvider |
| | 26 | | { |
| | 27 | | private readonly JsonValueKind _kind; |
| | 28 | | private Dictionary<string, DynamicJson>? _objectRepresentation; |
| | 29 | | private List<DynamicJson>? _arrayRepresentation; |
| | 30 | | private object? _value; |
| | 31 | |
|
| 0 | 32 | | public DynamicJson(string json): this(JsonDocument.Parse(json).RootElement) |
| | 33 | | { |
| 0 | 34 | | } |
| | 35 | |
|
| | 36 | | /// <summary> |
| | 37 | | /// |
| | 38 | | /// </summary> |
| | 39 | | /// <param name="element"></param> |
| 256 | 40 | | public DynamicJson(JsonElement element) |
| | 41 | | { |
| 256 | 42 | | _kind = element.ValueKind; |
| 256 | 43 | | switch (element.ValueKind) |
| | 44 | | { |
| | 45 | | case JsonValueKind.Object: |
| 98 | 46 | | _objectRepresentation = new Dictionary<string, DynamicJson>(); |
| 352 | 47 | | foreach (var item in element.EnumerateObject()) |
| | 48 | | { |
| 78 | 49 | | _objectRepresentation[item.Name] = new DynamicJson(item.Value); |
| | 50 | | } |
| | 51 | | break; |
| | 52 | | case JsonValueKind.Array: |
| 16 | 53 | | _arrayRepresentation = new List<DynamicJson>(); |
| 140 | 54 | | foreach (var item in element.EnumerateArray()) |
| | 55 | | { |
| 54 | 56 | | _arrayRepresentation.Add(new DynamicJson(item)); |
| | 57 | | } |
| | 58 | | break; |
| | 59 | | case JsonValueKind.String: |
| 14 | 60 | | _value = element.GetString(); |
| 14 | 61 | | break; |
| | 62 | | case JsonValueKind.Number: |
| 106 | 63 | | _value = new Number(element); |
| 106 | 64 | | break; |
| | 65 | | case JsonValueKind.True: |
| | 66 | | case JsonValueKind.False: |
| 12 | 67 | | _value = element.GetBoolean(); |
| 12 | 68 | | break; |
| | 69 | | case JsonValueKind.Null: |
| 10 | 70 | | _value = null; |
| 10 | 71 | | break; |
| | 72 | | default: |
| 0 | 73 | | throw new ArgumentOutOfRangeException(nameof(element), "Unsupported element kind"); |
| | 74 | | } |
| 114 | 75 | | } |
| | 76 | |
|
| 4 | 77 | | private DynamicJson(IEnumerable<KeyValuePair<string,DynamicJson>> properties) |
| | 78 | | { |
| 4 | 79 | | _kind = JsonValueKind.Object; |
| 4 | 80 | | _objectRepresentation = new Dictionary<string, DynamicJson>(); |
| 0 | 81 | | foreach (var property in properties) |
| | 82 | | { |
| 0 | 83 | | _objectRepresentation[property.Key] = property.Value; |
| | 84 | | } |
| 4 | 85 | | } |
| | 86 | |
|
| 2 | 87 | | private DynamicJson(IEnumerable<DynamicJson> array) |
| | 88 | | { |
| 2 | 89 | | _kind = JsonValueKind.Array; |
| 2 | 90 | | _arrayRepresentation = new List<DynamicJson>(); |
| 20 | 91 | | foreach (var item in array) |
| | 92 | | { |
| 8 | 93 | | if (item == null) |
| | 94 | | { |
| 2 | 95 | | _arrayRepresentation.Add(new DynamicJson((object?)null)); |
| | 96 | | } |
| | 97 | | else |
| | 98 | | { |
| 6 | 99 | | _arrayRepresentation.Add(item); |
| | 100 | | } |
| | 101 | | } |
| 2 | 102 | | } |
| | 103 | |
|
| 60 | 104 | | private DynamicJson(object? value) |
| | 105 | | { |
| 60 | 106 | | _value = value; |
| 60 | 107 | | switch (value) |
| | 108 | | { |
| | 109 | | case long l: |
| 4 | 110 | | _kind = JsonValueKind.Number; |
| 4 | 111 | | _value = new Number(l); |
| 4 | 112 | | break; |
| | 113 | | case int i: |
| 16 | 114 | | _kind = JsonValueKind.Number; |
| 16 | 115 | | _value = new Number(i); |
| 16 | 116 | | break; |
| | 117 | | case double d: |
| 8 | 118 | | _kind = JsonValueKind.Number; |
| 8 | 119 | | _value = new Number(d); |
| 8 | 120 | | break; |
| | 121 | | case float d: |
| 4 | 122 | | _kind = JsonValueKind.Number; |
| 4 | 123 | | _value = new Number(d); |
| 4 | 124 | | break; |
| 8 | 125 | | case bool b when b: |
| 4 | 126 | | _kind = JsonValueKind.True; |
| 4 | 127 | | break; |
| 4 | 128 | | case bool b when !b: |
| 4 | 129 | | _kind = JsonValueKind.False; |
| 4 | 130 | | break; |
| | 131 | | default: |
| 20 | 132 | | _kind = value == null ? JsonValueKind.Null : JsonValueKind.String; |
| | 133 | | break; |
| | 134 | | } |
| 20 | 135 | | } |
| | 136 | |
|
| | 137 | | public static DynamicJson Parse(string json) |
| | 138 | | { |
| 122 | 139 | | return Create(JsonDocument.Parse(json).RootElement); |
| | 140 | | } |
| | 141 | |
|
| | 142 | | /// <summary> |
| | 143 | | /// |
| | 144 | | /// </summary> |
| | 145 | | /// <param name="element"></param> |
| | 146 | | /// <returns></returns> |
| | 147 | | public static DynamicJson Create(JsonElement element) |
| | 148 | | { |
| 122 | 149 | | return new DynamicJson(element); |
| | 150 | | } |
| | 151 | |
|
| | 152 | | /// <summary> |
| | 153 | | /// |
| | 154 | | /// </summary> |
| | 155 | | /// <param name="writer"></param> |
| | 156 | | /// <exception cref="ArgumentOutOfRangeException"></exception> |
| | 157 | | public void WriteTo(Utf8JsonWriter writer) |
| | 158 | | { |
| 194 | 159 | | switch (_kind) |
| | 160 | | { |
| | 161 | | case JsonValueKind.Null: |
| | 162 | | case JsonValueKind.String: |
| 26 | 163 | | writer.WriteStringValue((string?)_value); |
| 26 | 164 | | break; |
| | 165 | | case JsonValueKind.Number: |
| 50 | 166 | | ((Number) _value!).WriteTo(writer); |
| 50 | 167 | | break; |
| | 168 | | case JsonValueKind.True: |
| | 169 | | case JsonValueKind.False: |
| 12 | 170 | | writer.WriteBooleanValue((bool)_value!); |
| 12 | 171 | | break; |
| | 172 | | case JsonValueKind.Object: |
| 98 | 173 | | writer.WriteStartObject(); |
| 396 | 174 | | foreach (var property in EnsureObject()) |
| | 175 | | { |
| 100 | 176 | | writer.WritePropertyName(property.Key); |
| 100 | 177 | | property.Value.WriteTo(writer); |
| | 178 | | } |
| 98 | 179 | | writer.WriteEndObject(); |
| 98 | 180 | | break; |
| | 181 | | case JsonValueKind.Array: |
| 8 | 182 | | writer.WriteStartArray(); |
| 72 | 183 | | foreach (var item in EnsureArray()) |
| | 184 | | { |
| 28 | 185 | | item.WriteTo(writer); |
| | 186 | | } |
| 8 | 187 | | writer.WriteEndArray(); |
| | 188 | | break; |
| | 189 | | } |
| 8 | 190 | | } |
| | 191 | |
|
| | 192 | | /// <summary> |
| | 193 | | /// |
| | 194 | | /// </summary> |
| | 195 | | /// <param name="arrayIndex"></param> |
| | 196 | | public DynamicJson this[int arrayIndex] |
| | 197 | | { |
| 8 | 198 | | get => GetValueAt(arrayIndex); |
| 12 | 199 | | set => SetValueAt(arrayIndex, value); |
| | 200 | | } |
| | 201 | |
|
| | 202 | | /// <summary> |
| | 203 | | /// |
| | 204 | | /// </summary> |
| | 205 | | /// <param name="propertyName"></param> |
| | 206 | | public DynamicJson this[string propertyName] |
| | 207 | | { |
| 0 | 208 | | get => GetPropertyValue(propertyName); |
| 2 | 209 | | set => SetValue(propertyName, value); |
| | 210 | | } |
| | 211 | |
|
| | 212 | | private object SetValueAt(int index, object value) |
| | 213 | | { |
| 12 | 214 | | if (!(value is DynamicJson dynamicJson)) |
| | 215 | | { |
| 4 | 216 | | dynamicJson = new DynamicJson(value); |
| | 217 | | } |
| 12 | 218 | | EnsureArray()[index] = dynamicJson; |
| 12 | 219 | | return value; |
| | 220 | | } |
| | 221 | |
|
| | 222 | | /// <summary> |
| | 223 | | /// |
| | 224 | | /// </summary> |
| | 225 | | /// <returns></returns> |
| | 226 | | public JsonElement ToJsonElement() |
| | 227 | | { |
| 0 | 228 | | var memoryStream = new MemoryStream(); |
| 0 | 229 | | var writer = new Utf8JsonWriter(memoryStream); |
| 0 | 230 | | WriteTo(writer); |
| 0 | 231 | | return JsonDocument.Parse(memoryStream.ToArray()).RootElement; |
| | 232 | | } |
| | 233 | |
|
| | 234 | | /// <inheritdoc /> |
| | 235 | | public override string ToString() |
| | 236 | | { |
| 66 | 237 | | using var memoryStream = new MemoryStream(); |
| 66 | 238 | | using (var writer = new Utf8JsonWriter(memoryStream)) |
| | 239 | | { |
| 66 | 240 | | WriteTo(writer); |
| 66 | 241 | | } |
| 66 | 242 | | return Encoding.UTF8.GetString(memoryStream.ToArray()); |
| 66 | 243 | | } |
| | 244 | |
|
| | 245 | | /// <inheritdoc /> |
| 234 | 246 | | DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) => new MetaObject(parameter, th |
| | 247 | |
|
| | 248 | | private IEnumerable GetDynamicEnumerable() |
| | 249 | | { |
| 4 | 250 | | if (_kind == JsonValueKind.Array) |
| | 251 | | { |
| 4 | 252 | | return EnsureArray(); |
| | 253 | | } |
| | 254 | |
|
| 0 | 255 | | return EnsureObject(); |
| | 256 | | } |
| | 257 | |
|
| | 258 | | private DynamicJson GetPropertyValue(string propertyName) |
| | 259 | | { |
| | 260 | |
|
| 88 | 261 | | if (EnsureObject().TryGetValue(propertyName, out DynamicJson element)) |
| | 262 | | { |
| 88 | 263 | | return element; |
| | 264 | | } |
| | 265 | |
|
| 0 | 266 | | throw new InvalidOperationException($"Property {propertyName} not found"); |
| | 267 | | } |
| | 268 | |
|
| | 269 | | private object? SetValue(string propertyName, object? value) |
| | 270 | | { |
| 48 | 271 | | if (!(value is DynamicJson json)) |
| | 272 | | { |
| 38 | 273 | | json = new DynamicJson(value); |
| | 274 | | } |
| | 275 | |
|
| 48 | 276 | | EnsureObject()[propertyName] = json; |
| 48 | 277 | | return value; |
| | 278 | | } |
| | 279 | |
|
| | 280 | | private List<DynamicJson> EnsureArray() |
| | 281 | | { |
| 44 | 282 | | if (_kind != JsonValueKind.Array) |
| | 283 | | { |
| 0 | 284 | | throw new InvalidOperationException($"Expected kind to be array but was {_kind} instead"); |
| | 285 | | } |
| | 286 | |
|
| | 287 | | Debug.Assert(_arrayRepresentation != null); |
| 44 | 288 | | return _arrayRepresentation!; |
| | 289 | | } |
| | 290 | |
|
| | 291 | | private Dictionary<string, DynamicJson> EnsureObject() |
| | 292 | | { |
| 234 | 293 | | if (_kind != JsonValueKind.Object) |
| | 294 | | { |
| 0 | 295 | | throw new InvalidOperationException($"Expected kind to be object but was {_kind} instead"); |
| | 296 | | } |
| | 297 | |
|
| | 298 | | Debug.Assert(_objectRepresentation != null); |
| 234 | 299 | | return _objectRepresentation!; |
| | 300 | | } |
| | 301 | |
|
| | 302 | | private object? EnsureValue() |
| | 303 | | { |
| 156 | 304 | | if (_kind == JsonValueKind.Object || _kind == JsonValueKind.Array) |
| | 305 | | { |
| 0 | 306 | | throw new InvalidOperationException($"Expected kind to be value but was {_kind} instead"); |
| | 307 | | } |
| | 308 | |
|
| 156 | 309 | | return _value; |
| | 310 | | } |
| | 311 | |
|
| | 312 | | private Number EnsureNumberValue() |
| | 313 | | { |
| 128 | 314 | | if (_kind != JsonValueKind.Number) |
| | 315 | | { |
| 4 | 316 | | throw new InvalidOperationException($"Expected kind to be number but was {_kind} instead"); |
| | 317 | | } |
| | 318 | |
|
| 124 | 319 | | return (Number) EnsureValue()!; |
| | 320 | | } |
| | 321 | |
|
| | 322 | | private DynamicJson GetValueAt(int index) |
| | 323 | | { |
| 8 | 324 | | return EnsureArray()[index]; |
| | 325 | | } |
| | 326 | |
|
| | 327 | | private class MetaObject : DynamicMetaObject |
| | 328 | | { |
| 2 | 329 | | private static readonly MethodInfo GetDynamicValueMethod = typeof(DynamicJson).GetMethod(nameof(GetPropertyV |
| | 330 | |
|
| 2 | 331 | | private static readonly MethodInfo GetDynamicEnumerableMethod = typeof(DynamicJson).GetMethod(nameof(GetDyna |
| | 332 | |
|
| 234 | 333 | | internal MetaObject(Expression parameter, IDynamicMetaObjectProvider value) : base(parameter, BindingRestric |
| | 334 | | { |
| 234 | 335 | | } |
| | 336 | |
|
| | 337 | | public override DynamicMetaObject BindGetMember(GetMemberBinder binder) |
| | 338 | | { |
| 68 | 339 | | var targetObject = Expression.Convert(Expression, LimitType); |
| | 340 | |
|
| 68 | 341 | | var arguments = new Expression[] { Expression.Constant(binder.Name) }; |
| 68 | 342 | | var getPropertyCall = Expression.Call(targetObject, GetDynamicValueMethod, arguments); |
| | 343 | |
|
| 68 | 344 | | var restrictions = BindingRestrictions.GetTypeRestriction(Expression, LimitType); |
| 68 | 345 | | return new DynamicMetaObject(getPropertyCall, restrictions); |
| | 346 | | } |
| | 347 | |
|
| | 348 | | public override DynamicMetaObject BindConvert(ConvertBinder binder) |
| | 349 | | { |
| 106 | 350 | | if (binder.Type == typeof(IEnumerable)) |
| | 351 | | { |
| 4 | 352 | | var targetObject = Expression.Convert(Expression, LimitType); |
| 4 | 353 | | var getPropertyCall = Expression.Call(targetObject, GetDynamicEnumerableMethod); |
| | 354 | |
|
| 4 | 355 | | var restrictions = BindingRestrictions.GetTypeRestriction(Expression, LimitType); |
| 4 | 356 | | return new DynamicMetaObject(getPropertyCall, restrictions); |
| | 357 | | } |
| 102 | 358 | | return base.BindConvert(binder); |
| | 359 | | } |
| | 360 | |
|
| | 361 | | public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) |
| | 362 | | { |
| 38 | 363 | | Expression targetObject = Expression.Convert(Expression, LimitType); |
| 38 | 364 | | var methodImplementation = typeof(DynamicJson).GetMethod(nameof(SetValue), BindingFlags.NonPublic | Bind |
| 38 | 365 | | var arguments = new Expression[2] { Expression.Constant(binder.Name), Expression.Convert(value.Expressio |
| | 366 | |
|
| 38 | 367 | | Expression setPropertyCall = Expression.Call(targetObject, methodImplementation, arguments); |
| 38 | 368 | | BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction(Expression, LimitType); |
| 38 | 369 | | DynamicMetaObject setProperty = new DynamicMetaObject(setPropertyCall, restrictions); |
| 38 | 370 | | return setProperty; |
| | 371 | | } |
| | 372 | | } |
| | 373 | |
|
| | 374 | |
|
| | 375 | | /// <summary> |
| | 376 | | /// |
| | 377 | | /// </summary> |
| | 378 | | /// <returns></returns> |
| | 379 | | public IEnumerable<DynamicJson> EnumerateArray() |
| | 380 | | { |
| 0 | 381 | | return EnsureArray(); |
| | 382 | | } |
| | 383 | |
|
| | 384 | | /// <summary> |
| | 385 | | /// |
| | 386 | | /// </summary> |
| | 387 | | /// <returns></returns> |
| | 388 | | public IEnumerable<KeyValuePair<string, DynamicJson>> EnumerateObject() |
| | 389 | | { |
| 0 | 390 | | return EnsureObject(); |
| | 391 | | } |
| | 392 | |
|
| | 393 | | /// <summary> |
| | 394 | | /// |
| | 395 | | /// </summary> |
| | 396 | | /// <returns></returns> |
| | 397 | | #pragma warning disable CA1720 // Identifier 'Object' contains type name |
| | 398 | | public static DynamicJson Object() |
| | 399 | | { |
| 4 | 400 | | return Object(System.Array.Empty<KeyValuePair<string, DynamicJson>>()); |
| | 401 | | } |
| | 402 | |
|
| | 403 | | /// <summary> |
| | 404 | | /// |
| | 405 | | /// </summary> |
| | 406 | | /// <returns></returns> |
| | 407 | | public static DynamicJson Object(IEnumerable<KeyValuePair<string, DynamicJson>> values) |
| | 408 | | { |
| 4 | 409 | | return new DynamicJson(values); |
| | 410 | | } |
| | 411 | | #pragma warning restore CA1720 |
| | 412 | |
|
| | 413 | | /// <summary> |
| | 414 | | /// |
| | 415 | | /// </summary> |
| | 416 | | /// <returns></returns> |
| | 417 | | public static DynamicJson Array() |
| | 418 | | { |
| 0 | 419 | | return Array(System.Array.Empty<DynamicJson>()); |
| | 420 | | } |
| | 421 | |
|
| | 422 | | /// <summary> |
| | 423 | | /// |
| | 424 | | /// </summary> |
| | 425 | | /// <returns></returns> |
| | 426 | | public static DynamicJson Array(IEnumerable<DynamicJson> values) |
| | 427 | | { |
| 0 | 428 | | return new DynamicJson(values); |
| | 429 | | } |
| | 430 | |
|
| | 431 | | /// <summary> |
| | 432 | | /// |
| | 433 | | /// </summary> |
| | 434 | | /// <param name="values"></param> |
| | 435 | | /// <returns></returns> |
| | 436 | | public static DynamicJson Array(params DynamicJson[] values) |
| | 437 | | { |
| 2 | 438 | | return new DynamicJson(values); |
| | 439 | | } |
| | 440 | |
|
| 16 | 441 | | public static explicit operator bool(DynamicJson json) => json.GetBoolean(); |
| 46 | 442 | | public static explicit operator int(DynamicJson json) => json.GetIn32(); |
| 24 | 443 | | public static explicit operator long(DynamicJson json) => json.GetLong(); |
| 16 | 444 | | public static explicit operator string?(DynamicJson json) => json.GetString(); |
| 26 | 445 | | public static explicit operator float(DynamicJson json) => json.GetFloat(); |
| 32 | 446 | | public static explicit operator double(DynamicJson json) => json.GetDouble(); |
| | 447 | |
|
| | 448 | |
|
| 2 | 449 | | public static explicit operator bool?(DynamicJson json) => json._kind == JsonValueKind.Null ? (bool?)null : json |
| 2 | 450 | | public static explicit operator int?(DynamicJson json) => json._kind == JsonValueKind.Null ? (int?)null : json.G |
| 2 | 451 | | public static explicit operator long?(DynamicJson json) => json._kind == JsonValueKind.Null ? (long?)null : json |
| 0 | 452 | | public static explicit operator float?(DynamicJson json) => json._kind == JsonValueKind.Null ? (float?)null : js |
| 0 | 453 | | public static explicit operator double?(DynamicJson json) => json._kind == JsonValueKind.Null ? (double?)null : |
| | 454 | |
|
| 8 | 455 | | public static implicit operator DynamicJson(int value) => new DynamicJson(value); |
| 0 | 456 | | public static implicit operator DynamicJson(long value) => new DynamicJson(value); |
| 0 | 457 | | public static implicit operator DynamicJson(double value) => new DynamicJson(value); |
| 0 | 458 | | public static implicit operator DynamicJson(float value) => new DynamicJson(value); |
| 0 | 459 | | public static implicit operator DynamicJson(bool value) => new DynamicJson(value); |
| 8 | 460 | | public static implicit operator DynamicJson(string? value) => new DynamicJson((object?)value); |
| 0 | 461 | | public static implicit operator DynamicJson(int? value) => new DynamicJson(value); |
| 0 | 462 | | public static implicit operator DynamicJson(long? value) => new DynamicJson(value); |
| 0 | 463 | | public static implicit operator DynamicJson(double? value) => new DynamicJson(value); |
| 0 | 464 | | public static implicit operator DynamicJson(float? value) => new DynamicJson(value); |
| 0 | 465 | | public static implicit operator DynamicJson(bool? value) => new DynamicJson(value); |
| | 466 | |
|
| 16 | 467 | | public string? GetString() => (string?)EnsureValue(); |
| | 468 | |
|
| | 469 | | public int GetIn32() |
| | 470 | | { |
| 46 | 471 | | var value = EnsureNumberValue().AsLong(); |
| 38 | 472 | | if (value > int.MaxValue || value < int.MinValue) |
| | 473 | | { |
| 8 | 474 | | throw new OverflowException(); |
| | 475 | | } |
| 30 | 476 | | return (int)value; |
| | 477 | | } |
| | 478 | |
|
| 24 | 479 | | public long GetLong() => EnsureNumberValue().AsLong(); |
| | 480 | | public float GetFloat() |
| | 481 | | { |
| 26 | 482 | | var value = EnsureNumberValue().AsDouble(); |
| 26 | 483 | | if (value > float.MaxValue || value < float.MinValue) |
| | 484 | | { |
| 8 | 485 | | throw new OverflowException(); |
| | 486 | | } |
| 18 | 487 | | return (float)value; |
| | 488 | | } |
| 32 | 489 | | public double GetDouble() => EnsureNumberValue().AsDouble(); |
| 16 | 490 | | public bool GetBoolean() => (bool)EnsureValue()!; |
| 12 | 491 | | public int GetArrayLength() => EnsureArray().Count; |
| 0 | 492 | | public DynamicJson GetProperty(string name) => GetPropertyValue(name); |
| | 493 | |
|
| | 494 | | public static DynamicJson Serialize<T>(T value, JsonSerializerOptions? options = null) |
| | 495 | | { |
| 2 | 496 | | var serialized = JsonSerializer.Serialize<T>(value, options); |
| 2 | 497 | | return new DynamicJson(JsonDocument.Parse(serialized).RootElement); |
| | 498 | | } |
| | 499 | |
|
| | 500 | | public static DynamicJson Serialize<T>(T value, ObjectSerializer serializer, CancellationToken cancellationToken |
| | 501 | | { |
| 0 | 502 | | using var memoryStream = new MemoryStream(); |
| 0 | 503 | | serializer.Serialize(memoryStream, value, typeof(T), cancellationToken); |
| 0 | 504 | | memoryStream.Position = 0; |
| 0 | 505 | | return new DynamicJson(JsonDocument.Parse(memoryStream).RootElement); |
| 0 | 506 | | } |
| | 507 | |
|
| | 508 | | public static async Task<DynamicJson> SerializeAsync<T>(T value, ObjectSerializer serializer, CancellationToken |
| | 509 | | { |
| 0 | 510 | | using var memoryStream = new MemoryStream(); |
| 0 | 511 | | await serializer.SerializeAsync(memoryStream, value, typeof(T), cancellationToken).ConfigureAwait(false); |
| 0 | 512 | | memoryStream.Position = 0; |
| 0 | 513 | | return new DynamicJson(JsonDocument.Parse(memoryStream).RootElement); |
| 0 | 514 | | } |
| | 515 | |
|
| | 516 | | public T Deserialize<T>(JsonSerializerOptions? options = null) |
| | 517 | | { |
| 0 | 518 | | return JsonSerializer.Deserialize<T>(ToString(), options); |
| | 519 | | } |
| | 520 | |
|
| | 521 | | public T Deserialize<T>(ObjectSerializer serializer, CancellationToken cancellationToken = default) |
| | 522 | | { |
| 0 | 523 | | var stream = new MemoryStream(Encoding.UTF8.GetBytes(ToString())); |
| 0 | 524 | | return (T) serializer.Deserialize(stream, typeof(T), cancellationToken); |
| | 525 | | } |
| | 526 | |
|
| | 527 | | public async Task<T> DeserializeAsync<T>(ObjectSerializer serializer, CancellationToken cancellationToken = defa |
| | 528 | | { |
| 0 | 529 | | var stream = new MemoryStream(Encoding.UTF8.GetBytes(ToString())); |
| 0 | 530 | | return (T) await serializer.DeserializeAsync(stream, typeof(T), cancellationToken).ConfigureAwait(false); |
| 0 | 531 | | } |
| | 532 | |
|
| | 533 | | private struct Number |
| | 534 | | { |
| | 535 | | public Number(in JsonElement element) |
| | 536 | | { |
| 106 | 537 | | _hasDouble = element.TryGetDouble(out _double); |
| 106 | 538 | | _hasLong = element.TryGetInt64(out _long); |
| 106 | 539 | | } |
| | 540 | |
|
| | 541 | | public Number(long l) |
| | 542 | | { |
| 20 | 543 | | _long = l; |
| 20 | 544 | | _hasLong = true; |
| 20 | 545 | | _double = default; |
| 20 | 546 | | _hasDouble = false; |
| 20 | 547 | | } |
| | 548 | |
|
| | 549 | | private long _long; |
| | 550 | | private bool _hasLong; |
| | 551 | | private double _double; |
| | 552 | | private bool _hasDouble; |
| | 553 | |
|
| | 554 | | public Number(double d) |
| | 555 | | { |
| 12 | 556 | | _long = default; |
| 12 | 557 | | _hasLong = false; |
| 12 | 558 | | _double = d; |
| 12 | 559 | | _hasDouble = true; |
| 12 | 560 | | } |
| | 561 | |
|
| | 562 | | public void WriteTo(Utf8JsonWriter writer) |
| | 563 | | { |
| 50 | 564 | | if (_hasDouble) |
| | 565 | | { |
| 26 | 566 | | writer.WriteNumberValue(_double); |
| | 567 | | } |
| | 568 | | else |
| | 569 | | { |
| 24 | 570 | | writer.WriteNumberValue(_long); |
| | 571 | | } |
| 24 | 572 | | } |
| | 573 | |
|
| | 574 | | public long AsLong() |
| | 575 | | { |
| 66 | 576 | | if (!_hasLong) |
| | 577 | | { |
| 8 | 578 | | throw new FormatException(); |
| | 579 | | } |
| 58 | 580 | | return _long; |
| | 581 | | } |
| | 582 | |
|
| | 583 | | public double AsDouble() |
| | 584 | | { |
| 58 | 585 | | return _double; |
| | 586 | | } |
| | 587 | | } |
| | 588 | |
|
| | 589 | | } |
| | 590 | | } |