ChangedJSONFieldPaths returns the set of dot-delimited field paths that differ between two JSON bodies — value changes, type changes, and removed fields (pure additions are NOT returned, since a brand-new field is not "noise" the way a drifting value is). Array elements normalize to a "[]" suffix (c
(expJSON, actJSON string, known map[string][]string, excludeRecordedValue func(string) bool)
| 124 | // redacted (recorded value matches a Mock.Noise regex) so secret fields are |
| 125 | // not re-flagged as schema noise. |
| 126 | func ChangedJSONFieldPaths(expJSON, actJSON string, known map[string][]string, excludeRecordedValue func(string) bool) []string { |
| 127 | if !json.Valid([]byte(expJSON)) || !json.Valid([]byte(actJSON)) { |
| 128 | return nil |
| 129 | } |
| 130 | |
| 131 | var exp, act interface{} |
| 132 | if err := json.Unmarshal([]byte(expJSON), &exp); err != nil { |
| 133 | return nil |
| 134 | } |
| 135 | if err := json.Unmarshal([]byte(actJSON), &act); err != nil { |
| 136 | return nil |
| 137 | } |
| 138 | |
| 139 | idx := buildNoiseIndex(known) |
| 140 | |
| 141 | expMaps := pathMaps{types: map[string]string{}, values: map[string]string{}} |
| 142 | actMaps := pathMaps{types: map[string]string{}, values: map[string]string{}} |
| 143 | |
| 144 | collectJSON(exp, "", idx, &expMaps) |
| 145 | collectJSON(act, "", idx, &actMaps) |
| 146 | |
| 147 | _, removed, typeChanges, valueChanges := diffMaps(expMaps, actMaps) |
| 148 | |
| 149 | keep := func(path string) bool { |
| 150 | if excludeRecordedValue == nil { |
| 151 | return true |
| 152 | } |
| 153 | if v, ok := expMaps.values[path]; ok && excludeRecordedValue(v) { |
| 154 | return false |
| 155 | } |
| 156 | return true |
| 157 | } |
| 158 | |
| 159 | out := make([]string, 0, len(valueChanges)+len(typeChanges)+len(removed)) |
| 160 | for _, group := range [][]string{valueChanges, typeChanges, removed} { |
| 161 | for _, p := range group { |
| 162 | if keep(p) { |
| 163 | out = append(out, p) |
| 164 | } |
| 165 | } |
| 166 | } |
| 167 | if len(out) == 0 { |
| 168 | return nil |
| 169 | } |
| 170 | return out |
| 171 | } |
| 172 | |
| 173 | // JSONFieldDiffs returns field-level diffs between two JSON documents with |
| 174 | // recorded/live values attached, for mock-mismatch reporting. It walks both |