| File: src\Shared\Json\JsonFlattener.cs | Web Access |
| Project: src\src\Aspire.Cli\Aspire.Cli.csproj (aspire) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Text.Json.Nodes; namespace Aspire.Shared.Json; /// <summary> /// Provides utility methods for flattening and unflattening JSON objects using colon-separated keys. /// </summary> internal static class JsonFlattener { /// <summary> /// Flattens a JsonObject using colon-separated keys for configuration compatibility. /// </summary> public static JsonObject FlattenJsonObject(JsonObject source) { var result = new JsonObject(); FlattenJsonObjectRecursive(source, string.Empty, result); return result; } /// <summary> /// Unflattens a JsonObject that uses colon-separated keys back into a nested structure. /// </summary> public static JsonObject UnflattenJsonObject(JsonObject source) { var result = new JsonObject(); foreach (var kvp in source) { var keys = kvp.Key.Split(':'); var current = result; for (var i = 0; i < keys.Length - 1; i++) { var key = keys[i]; if (!current.TryGetPropertyValue(key, out var existing) || existing is not JsonObject) { var newObject = new JsonObject(); current[key] = newObject; current = newObject; } else { current = existing.AsObject(); } } current[keys[^1]] = kvp.Value?.DeepClone(); } return result; } private static void FlattenJsonObjectRecursive(JsonObject source, string prefix, JsonObject result) { foreach (var kvp in source) { var key = string.IsNullOrEmpty(prefix) ? kvp.Key : string.IsNullOrEmpty(kvp.Key) ? prefix : $"{prefix}:{kvp.Key}"; if (kvp.Value is JsonObject nestedObject) { FlattenJsonObjectRecursive(nestedObject, key, result); } else if (kvp.Value is JsonArray array) { for (var i = 0; i < array.Count; i++) { var arrayKey = $"{key}:{i}"; if (array[i] is JsonObject arrayObject) { FlattenJsonObjectRecursive(arrayObject, arrayKey, result); } else { result[arrayKey] = array[i]?.DeepClone(); } } } else { result[key] = kvp.Value?.DeepClone(); } } } }