fix: refactor dotted key expansion to handle nested objects recursively - #173
Conversation
📝 WalkthroughWalkthroughThe PR modifies ChangesRecursive dotted-key expansion in JSON rendering
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@SW.Bitween.NativeAdapters/JsonMapper/ScribanJsonHelper.cs`:
- Around line 143-145: The loop that calls SetByPath for each prop after
ExpandDottedKeys can silently overwrite when dotted paths collide (e.g.,
existing "a" vs incoming "a.b"); modify the logic to detect such collisions and
throw instead of overwriting: either add a pre-check in the caller before
SetByPath that inspects the current result for existing nodes along the dotted
path (using prop.Name and the structure returned by ExpandDottedKeys) or harden
SetByPath itself to validate each path segment (in SetByPath, when
traversing/creating nodes, throw an exception if a scalar value exists where an
object is required or an object exists where a scalar is being set). Ensure the
thrown exception includes the conflicting path and the names of the existing and
incoming node types so callers can fail fast on collisions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: b0c42f40-aede-40db-aaaa-951e934d2e91
📒 Files selected for processing (1)
SW.Bitween.NativeAdapters/JsonMapper/ScribanJsonHelper.cs
| foreach (var prop in obj.Properties()) | ||
| SetByPath(result, prop.Name, ExpandDottedKeys(prop.Value)); | ||
| return result; |
There was a problem hiding this comment.
Detect and block dotted-path collisions to prevent silent data loss.
Line 144 now applies SetByPath recursively at every depth. If an object has both a and a.b, one value is overwritten based on property order. Please fail fast on collision instead of replacing existing nodes.
💡 Proposed fix
private static void SetByPath(JObject root, string path, JToken value)
{
var parts = path.Split('.');
JObject current = root;
for (int i = 0; i < parts.Length - 1; i++)
{
var part = parts[i];
- if (current[part] is not JObject child)
- {
- child = new JObject();
- current[part] = child;
- }
- current = child;
+ var existing = current[part];
+ if (existing is JObject child)
+ {
+ current = child;
+ continue;
+ }
+
+ if (existing != null)
+ throw new InvalidOperationException(
+ $"Cannot expand dotted path '{path}': segment '{part}' is already a non-object value.");
+
+ var newChild = new JObject();
+ current[part] = newChild;
+ current = newChild;
}
- current[parts[^1]] = value;
+ var leaf = parts[^1];
+ if (current[leaf] is JObject && value is not JObject)
+ throw new InvalidOperationException(
+ $"Cannot set path '{path}': destination is already an object.");
+
+ current[leaf] = value;
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@SW.Bitween.NativeAdapters/JsonMapper/ScribanJsonHelper.cs` around lines 143 -
145, The loop that calls SetByPath for each prop after ExpandDottedKeys can
silently overwrite when dotted paths collide (e.g., existing "a" vs incoming
"a.b"); modify the logic to detect such collisions and throw instead of
overwriting: either add a pre-check in the caller before SetByPath that inspects
the current result for existing nodes along the dotted path (using prop.Name and
the structure returned by ExpandDottedKeys) or harden SetByPath itself to
validate each path segment (in SetByPath, when traversing/creating nodes, throw
an exception if a scalar value exists where an object is required or an object
exists where a scalar is being set). Ensure the thrown exception includes the
conflicting path and the names of the existing and incoming node types so
callers can fail fast on collisions.
Summary by CodeRabbit