For an object with duplicate keys, db[key] and db.to_python()[key] silently disagree with each other on the same file; one returns the first occurrence, the other the last.
Root cause
IndexStorage._child_by_key_cached (storage.py) scans children forward and returns the first match:
for i in range(start, end):
...
if unpacked[2] == key_id:
return self._make_record(child_id, unpacked, parent_offset)
to_python() (lazy.py) instead re-parses the raw bytes with json.loads, which is typical of JSON implementations, and means it keeps the last occurrence of a duplicate key.
Reproduction
import bytejson
p = "./tmp/dup.json"
open(p, "w").write('{"a":1,"a":2,"a":3}')
db = bytejson.open(p)
print(db["a"]) # 1
print(db.to_python()["a"]) # 3
Observed
db['a'] = 1
db.to_python()['a'] = 3
Expected: both access paths should agree (standard practice is "last key wins", matching json.loads and to_python()).
For an object with duplicate keys,
db[key]anddb.to_python()[key]silently disagree with each other on the same file; one returns the first occurrence, the other the last.Root cause
IndexStorage._child_by_key_cached(storage.py) scans children forward and returns the first match:to_python()(lazy.py) instead re-parses the raw bytes withjson.loads, which is typical of JSON implementations, and means it keeps the last occurrence of a duplicate key.Reproduction
Observed
Expected: both access paths should agree (standard practice is "last key wins", matching
json.loadsandto_python()).