using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; using Elsa.Extensions; namespace Elsa.Api.Client.Extensions; /// /// Provides extension methods for . /// public static class JsonObjectExtensions { /// /// Returns true if the specified represents an activity. /// public static bool IsActivity(this JsonObject obj) { return obj.ContainsKey("type") && obj.ContainsKey("id") && obj.ContainsKey("version"); } /// /// Serializes the specified value to a . /// /// The value to serialize. /// The to use. /// A representing the specified value. public static JsonNode SerializeToNode(this object value, JsonSerializerOptions? options = null) { options ??= (new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, }).WithConverters(new JsonStringEnumConverter()); return JsonSerializer.SerializeToNode(value, options)!; } /// /// Serializes the specified value to a . /// /// The value to serialize. /// The to use. /// A representing the specified value. public static JsonArray SerializeToArray(this object value, JsonSerializerOptions? options = null) { options ??= new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; return JsonSerializer.SerializeToNode(value, options)!.AsArray(); } /// /// Serializes the specified value to a . /// /// The value to serialize. /// The to use. /// A representing the specified value. public static JsonArray SerializeToArray(this IEnumerable value, JsonSerializerOptions? options = null) { options ??= new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; return JsonSerializer.SerializeToNode(value, options)!.AsArray(); } /// /// Deserializes the specified to the specified type. /// /// The to deserialize. /// The to use. /// The type to deserialize to. /// The deserialized value. public static T Deserialize(this JsonNode value, JsonSerializerOptions? options = null) { options ??= new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; if (value is JsonObject jsonObject) return JsonSerializer.Deserialize(jsonObject, options)!; if (value is JsonArray jsonArray) return JsonSerializer.Deserialize(jsonArray, options)!; if (typeof(T).IsEnum || (Nullable.GetUnderlyingType(typeof(T))?.IsEnum ?? false)) { if (value.GetValueKind() == JsonValueKind.Null) return default!; return (T)Enum.Parse(Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T), value.ToString()); } if (value is JsonValue jsonValue) return jsonValue.GetValue(); throw new NotSupportedException($"Cannot deserialize {value.GetType()} to {typeof(T)}."); } /// /// Sets the property value of the specified model. /// /// The model to set the property value on. /// The value to set. /// The path to the property. public static void SetProperty(this JsonObject model, JsonNode? value, params string[] path) { model = GetPropertyContainer(model, path); model[path.Last()] = value?.SerializeToNode(); } /// /// Sets the property value of the specified model. /// /// The model to set the property value on. /// The value to set. /// The path to the property. public static void SetProperty(this JsonObject model, JsonArray? value, params string[] path) { model = GetPropertyContainer(model, path); model[path.Last()] = value?.SerializeToNode(); } /// /// Sets the property value of the specified model. /// /// The model to set the property value on. /// The value to set. /// The path to the property. public static void SetProperty(this JsonObject model, IEnumerable value, params string[] path) { model = GetPropertyContainer(model, path); model[path.Last()] = new JsonArray(value.Select(x => x.SerializeToNode()).ToArray()); } /// /// Gets the property value of the specified model. /// /// The model to get the property value from. /// The path to the property. /// The property value. public static JsonNode? GetProperty(this JsonObject model, params string[] path) { var currentModel = model; foreach (var prop in path.SkipLast(1)) { if (currentModel[prop] is not JsonObject value) return null; currentModel = value; } return currentModel[path.Last()]; } /// /// Gets the property value of the specified model. /// /// The model to get the property value from. /// The path to the property. /// The type to deserialize to. /// The property value. public static T? TryGetProperty(this JsonObject model, params string[] path) { try { return model.GetProperty(path); } catch (Exception e) { return default; } } /// /// Gets the property value of the specified model. /// /// The model to get the property value from. /// The path to the property. /// The type to deserialize to. /// The property value. public static T? GetProperty(this JsonObject model, params string[] path) { var property = GetProperty(model, path); return property != null ? property.Deserialize() : default; } /// /// Gets the property value of the specified model. /// /// The model to get the property value from. /// The to use when deserializing. /// The path to the property. /// The type to deserialize to. /// The property value. public static T? GetProperty(this JsonObject model, JsonSerializerOptions options, params string[] path) { var property = GetProperty(model, path); return property != null ? property.Deserialize(options) : default; } /// /// Returns the property container of the specified model. /// /// The model to set the property value on. /// The path to the property. private static JsonObject GetPropertyContainer(this JsonObject model, params string[] path) { foreach (var prop in path.SkipLast(1)) { var property = model[prop] as JsonObject ?? new JsonObject(); model[prop] = property; model = property; } return model; } }