Preserve arrays under unflatten when safe and object are both set - #194
Open
spokodev wants to merge 1 commit into
Open
Preserve arrays under unflatten when safe and object are both set#194spokodev wants to merge 1 commit into
spokodev wants to merge 1 commit into
Conversation
`safe` is documented to make "both flatten and unflatten preserve arrays
and their contents", but with `object: true` also set, `unflatten` turns a
preserved array back into a plain object:
const opts = { safe: true, object: true }
unflatten(flatten({ tags: ['a', 'b', 'c'] }, opts), opts)
// { tags: { '0': 'a', '1': 'b', '2': 'c' } } -- no longer an array
`unflatten` never truly preserves arrays; it only rebuilds them as a side
effect of the numeric-key -> array logic, which `object: true` disables. Its
"messy objects" reduce re-flattens every container value, including a
`safe`-kept array, back into the flat keyspace, and it is then rebuilt as an
object. `safe` alone round-trips correctly because the array is rebuilt
numerically.
Pass a `safe` array through the reduce instead of re-flattening it, so it
survives unchanged regardless of `object`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The README says
safemakes "bothflattenandunflattenpreserve arrays and their contents". But whenobject: trueis also set,unflattenturns a preserved array back into a plain object:safeandobjectare orthogonal (safe= keep existing arrays;object= don't turn numeric-keyed objects into arrays) and combining them is legitimate, butobjectoverridessafe's array preservation.safealone round-trips correctly.Root cause
unflattennever truly preserves arrays — it only rebuilds them as a side effect of the numeric-key → array branch (typeof key2 === 'number' && !opts.object). Its "messy objects" reduce re-flattens every container value, including asafe-kept array, back into the flat keyspace; withobject: truethe rebuild produces a plain object instead of an array.safeis never consulted inunflattento keep an already-array value intact.Fix
In the reduce, pass a
safearray through as a leaf instead of re-flattening it, so it survives the reconstruction unchanged regardless ofobject.Tests
Added a
.safecase asserting{ safe: true, object: true }round-trips{ tags: ['red','green','blue'] }as an array. It fails onmasterand passes with the fix; the suite andstandardare green.