diff options
| author | Stefan Majewsky <majewsky@gmx.net> | 2026-06-04 16:13:13 +0200 |
|---|---|---|
| committer | Stefan Majewsky <majewsky@gmx.net> | 2026-06-04 16:13:13 +0200 |
| commit | 2d71e70097ba48d5c1e59f455bd2499ab14844e3 (patch) | |
| tree | 5a6cebf4dfc87620efbcd7dd164252c37c688898 /jsonmatch/machinery.go | |
| parent | de1908cc7a11076f808f19f2d3ce115cda4bccd4 (diff) | |
| download | go-gg-2d71e70097ba48d5c1e59f455bd2499ab14844e3.tar.gz | |
jsonmatch: allow embedding custom Diffable instances within Object and Array
Diffstat (limited to 'jsonmatch/machinery.go')
| -rw-r--r-- | jsonmatch/machinery.go | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/jsonmatch/machinery.go b/jsonmatch/machinery.go index f3f5348..a10251a 100644 --- a/jsonmatch/machinery.go +++ b/jsonmatch/machinery.go @@ -26,7 +26,7 @@ func marshalExpectedForDiff(value any) string { func marshalActualForDiff(value any) string { // `actual` values are always safe to marshal because they were - // unmarshaled from JSON into any and thus can only contain safe + // unmarshaled from JSON into any and thus can only contain safe types buf, err := json.Marshal(value) if err != nil { // this line is therefore unreachable in tests and only exists as defense in depth @@ -121,8 +121,9 @@ func keyIntoPointerFragment(key string) string { } const ( - kindValueMismatch = "value mismatch" - kindTypeMismatch = "type mismatch" + kindValueMismatch = "value mismatch" + kindTypeMismatch = "type mismatch" + kindDispatchFailed = "dispatch failed" ) // NOTE: getDiffsForValue is the main part of the recursion to generate the diff. @@ -168,6 +169,29 @@ func getDiffsForValue(path []pathElement, expected, actual any) []Diff { } } + // generic handling for custom Diffables + // (if any unexpected error occurs here, we fall back to the default handling) + if diffable, ok := expected.(Diffable); ok { + // `actual` values are always safe to marshal because they were + // unmarshaled from JSON into any and thus can only contain safe types + buf, err := json.Marshal(actual) + if err != nil { + // this branch is therefore unreachable in tests and only exists as defense in depth + return []Diff{{ + Kind: kindDispatchFailed, + Pointer: pathIntoPointer(path), + ExpectedJSON: fmt.Sprintf("<custom diffable: %#v>", diffable), + ActualJSON: fmt.Sprintf("<marshal error: %s>", err.Error()), + }} + } + diffs := diffable.DiffAgainst(buf) + for idx, diff := range diffs { + diff.Pointer = pathIntoPointer(path) + diff.Pointer + diffs[idx] = diff + } + return diffs + } + // generic handling for values or structures that we do not recurse into further: // check that `expected` encodes to JSON in an equivalent way to `actual` actualJSON := marshalActualForDiff(actual) |
