Documentation
¶
Overview ¶
Package jsonmerge implements RFC 7386 (JSON Merge Patch) on top of stdlib encoding/json's `any` representation.
parse applies merge patches to documents with it. The algorithm is small, but it has a few subtle rules worth restating:
- When the patch is an object, recursively merge it into the target (which is also coerced to an object — non-object targets are replaced wholesale).
- When the patch is anything else (primitive, array, null), the patch replaces the target.
- Within an object patch, a `null` value at a key REMOVES the key from the target. This is the only way to express deletion.
- Arrays are NOT merged element-wise — the patch's array replaces the target's array entirely. Element-wise array patching needs RFC 6902 (JSON Patch), not RFC 7386.
The functions here operate on `any` decoded from JSON via stdlib encoding/json. Callers serialise both target and patch to JSON and decode them with `json.Unmarshal` before calling Apply.
Example:
target := map[string]any{"a": 1, "b": map[string]any{"x": 1}}
patch := map[string]any{"b": map[string]any{"x": nil, "y": 2}}
merged := jsonmerge.Apply(target, patch)
// merged == map[string]any{"a": 1, "b": map[string]any{"y": 2}}
Merging is non-destructive on the target: the function returns a new value rather than mutating the input. Nested maps inside the target ARE shared with the result (the implementation copies only when a value is rewritten); callers that need a deep clone should marshal and unmarshal through encoding/json before applying patches.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Apply ¶
Apply returns the result of merging patch into target per RFC 7386. Both arguments are read-only — Apply does not mutate them.
Top-level behaviour:
- patch is not an object (string, number, bool, array, nil) → return patch verbatim. The target is replaced.
- patch is an object → recursively merge each key into target, coercing target to an object first if it isn't already.
nil patch is a special case: per RFC 7386 it semantically means "replace target with null." Apply returns nil.
func ApplyAll ¶
ApplyAll merges layers in order from index 0 (lowest precedence) to the last (highest precedence). Each layer is applied as a JSON Merge Patch onto the accumulated result. An empty layers slice returns the zero value (nil).
A nil layer is treated as an ABSENT tier (no override) and skipped — the common N-tier case where a tier supplied no config. Consequently ApplyAll cannot express a top-level JSON `null` "reset to null": a decoded JSON null and an absent layer are both Go nil and indistinguishable here. If you need RFC 7386 top-level null-replace semantics, call Apply(result, nil) directly (it returns nil).
Use this for the canonical N-tier override pattern: pass `[]any{platformConfig, tenantConfig, projectConfig, serviceConfig, instanceConfig}` and get the effective resolved config.
Types ¶
This section is empty.