AllenNeuralDynamics / AllenNeuralDynamics/aind-json-utils-test-repo
Add module to merge json files
- Vorherrschende Sprache
- Python
- Sterne
- 0
- Forks
- 0
- PR-Merge-Kennzahlen
- Keine gemergten PRs in 30 T.
Beschreibung
## Summary
Create a module that merges two JSON files using a precedence-based strategy. A designated `main.json` file acts as the authoritative source — its existing values are never overwritten. A second "incoming" JSON file provides supplemental data that fills in missing keys only.
---
## Requirements
### Input
- The module accepts two JSON file paths as input.
- One file is always designated as `main.json` (the primary/authoritative source).
- The other file is the **incoming** JSON (the secondary/supplemental source).
### Merge Behavior
1. **Top-level keys that exist only in `main.json`** → preserved as-is.
2. **Top-level keys that exist only in the incoming JSON** → added to the merged result.
3. **Top-level keys that exist in both files:**
- If the value in `main.json` is **already populated** (non-null, non-empty), it takes precedence and must **not** be overwritten.
- If the value in `main.json` is `null`, `""`, `{}`, or `[]` (empty/unset), the incoming value may fill it in.
4. **Nested objects (recursive merge):**
- When both files have an object at the same key, the merge should recurse into the nested structure and apply the same precedence rules at every level.
- `main.json` values always win at any depth if they are populated.
5. **Arrays:**
- If `main.json` has a non-empty array at a given key, it is preserved entirely (no element-level merge).
- If `main.json` has an empty array and the incoming file has a non-empty one, the incoming array is used.
### Output
- The module returns (or writes) the merged JSON result.
---
## Example
**`main.json`**
```json
{
"name": "Acme Corp",
"address": {
"street": "123 Main St",
"city": "",
"state": "WA"
},
"tags": ["enterprise"],
"metadata": {
"created_by": "admin",
"notes": null
},
"contacts": []
}
```
**`incoming.json`**
```json
{
"name": "Acme Corporation",
"address": {
"street": "123 Main St",
"city": "Seattle",
"state": "WA",
"zip": "98101"
},
"tags": ["startup", "west-coast"],
"metadata": {
"created_by": "import-script",
"notes": "Imported from CRM",
"source": "crm-v2"
},
"contacts": [
{ "email": "info@example.com" }
],
"industry": "Technology"
}
```
**Expected merged result:**
```json
{
"name": "Acme Corp",
"address": {
"street": "123 Main St",
"city": "Seattle",
"state": "WA",
"zip": "98101"
},
"tags": ["enterprise"],
"metadata": {
"created_by": "admin",
"notes": "Imported from CRM",
"source": "crm-v2"
},
"contacts": [
{ "email": "info@acme.com" }
],
"industry": "Technology"
}
```
### Why each key resolved the way it did
| Key | Resolution | Reason |
|---|---|---|
| `name` | `"Acme Corp"` | Main is populated → preserved |
| `address.street` | `"123 Main St"` | Main is populated → preserved |
| `address.city` | `"Seattle"` | Main is empty string → incoming fills it |
| `address.state` | `"WA"` | Main is populated → preserved |
| `address.zip` | `"98101"` | Only in incoming → added |
| `tags` | `["enterprise"]` | Main has non-empty array → preserved |
| `metadata.created_by` | `"admin"` | Main is populated → preserved |
| `metadata.notes` | `"Imported from CRM"` | Main is null → incoming fills it |
| `metadata.source` | `"crm-v2"` | Only in incoming → added |
| `contacts` | `[{ "email": "info@example.com" }]` | Main is empty array → incoming fills it |
| `industry` | `"Technology"` | Only in incoming → added |
---
## Acceptance Criteria
- [ ] Module reads two JSON files from disk (or accepts two parsed objects).
- [ ] Merge is recursive for nested objects.
- [ ] `main.json` populated values are never overwritten at any depth.
- [ ] Empty/null values in `main.json` are filled by incoming data.
- [ ] Keys unique to either file appear in the final output.
- [ ] Non-empty arrays in `main.json` are preserved without element-level merging.
- [ ] Unit tests cover: flat merge, deep merge, empty-value replacement, array precedence, and keys unique to each file.
- [ ] Code handles edge cases: missing files, invalid JSON, deeply nested structures, and mismatched types at the same key.
Beitragsleitfaden
Bewertung
Dieses Issue wurde noch nicht bewertet.