From 4f588833c211eebd0083c250b9fd8e847d877afd Mon Sep 17 00:00:00 2001 From: hamzaalqurneh Date: Thu, 21 May 2026 13:11:02 +0300 Subject: [PATCH] fix: refactor dotted key expansion to handle nested objects recursively --- .../JsonMapper/ScribanJsonHelper.cs | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/SW.Bitween.NativeAdapters/JsonMapper/ScribanJsonHelper.cs b/SW.Bitween.NativeAdapters/JsonMapper/ScribanJsonHelper.cs index d2b506d5..59dff730 100644 --- a/SW.Bitween.NativeAdapters/JsonMapper/ScribanJsonHelper.cs +++ b/SW.Bitween.NativeAdapters/JsonMapper/ScribanJsonHelper.cs @@ -61,14 +61,8 @@ public static string Render(string scribanTemplate, string inputJson) throw new InvalidOperationException($"Template produced invalid JSON: {ex.Message}\n\nRendered:\n{rendered}"); } - // 8. Expand dotted keys into nested objects (e.g. "buyer.email" → {buyer:{email:...}}) - var result = new JObject(); - foreach (var prop in flat.Properties()) - { - SetByPath(result, prop.Name, prop.Value); - } - - return result.ToString(Formatting.Indented); + // 8. Expand dotted keys into nested objects recursively at all depths + return ExpandDottedKeys(flat).ToString(Formatting.Indented); } // ─── Helpers ────────────────────────────────────────────────────────────── @@ -140,6 +134,26 @@ public override bool TryGetValue(TemplateContext context, SourceSpan span, strin } } + /// Recursively expands dotted keys in all JObjects at every depth, including inside arrays. + private static JToken ExpandDottedKeys(JToken token) + { + if (token is JObject obj) + { + var result = new JObject(); + foreach (var prop in obj.Properties()) + SetByPath(result, prop.Name, ExpandDottedKeys(prop.Value)); + return result; + } + if (token is JArray arr) + { + var result = new JArray(); + foreach (var item in arr) + result.Add(ExpandDottedKeys(item)); + return result; + } + return token; + } + /// Sets a value at a dot-separated path inside a JObject, creating intermediate objects as needed. private static void SetByPath(JObject root, string path, JToken value) {