-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Accept number-like keys in JSON Pointers
- Loading branch information
1 parent
1e10b14
commit 0a1ac0a
Showing
5 changed files
with
185 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package jd | ||
|
||
import "strconv" | ||
|
||
// jsonStringOrInteger is a string unless it needs to be a number. It's | ||
// created only when encountering an integer token in a JSON | ||
// Pointer. Because the JSON Pointer spec doesn't quote strings, it's | ||
// impossible to tell if an integer is supposed to be an array index or a | ||
// map key. Rather than forbidding map keys that look like integers, we | ||
// defer determining the concrete type until the token is actually | ||
// used. When indexing into an object it's a string. When indexing into a | ||
// list it's an integer. | ||
type jsonStringOrInteger string | ||
|
||
var _ JsonNode = jsonStringOrInteger("") | ||
|
||
func (sori jsonStringOrInteger) Json(_ ...Metadata) string { | ||
return renderJson(sori.raw()) | ||
} | ||
|
||
func (sori jsonStringOrInteger) Yaml(_ ...Metadata) string { | ||
return renderYaml(sori.raw()) | ||
} | ||
|
||
func (sori jsonStringOrInteger) raw() interface{} { | ||
return string(sori) | ||
} | ||
|
||
func (sori jsonStringOrInteger) Equals(node JsonNode, metadata ...Metadata) bool { | ||
switch node.(type) { | ||
case jsonString: | ||
return jsonString(sori).Equals(node, metadata...) | ||
case jsonNumber: | ||
i, err := strconv.Atoi(string(sori)) | ||
if err != nil { | ||
return false | ||
} | ||
return jsonNumber(i).Equals(node, metadata...) | ||
default: | ||
return false | ||
} | ||
} | ||
|
||
func (sori jsonStringOrInteger) hashCode(metadata []Metadata) [8]byte { | ||
return jsonString(sori).hashCode(metadata) | ||
} | ||
|
||
func (sori jsonStringOrInteger) Diff(node JsonNode, metadata ...Metadata) Diff { | ||
return sori.diff(node, make(path, 0), metadata, getPatchStrategy(metadata)) | ||
} | ||
|
||
func (sori jsonStringOrInteger) diff( | ||
node JsonNode, | ||
path path, | ||
metadata []Metadata, | ||
strategy patchStrategy, | ||
) Diff { | ||
switch node.(type) { | ||
case jsonString: | ||
return jsonString(sori).Diff(node, metadata...) | ||
case jsonNumber: | ||
i, err := strconv.Atoi(string(sori)) | ||
if err != nil { | ||
return jsonString(sori).Diff(node, metadata...) | ||
} | ||
return jsonNumber(i).Diff(node, metadata...) | ||
default: | ||
return jsonString(sori).Diff(node, metadata...) | ||
} | ||
} | ||
|
||
func (sori jsonStringOrInteger) Patch(d Diff) (JsonNode, error) { | ||
return patchAll(jsonString(sori), d) | ||
} | ||
|
||
func (sori jsonStringOrInteger) patch( | ||
pathBehind, pathAhead path, | ||
oldValue, newValue []JsonNode, | ||
strategy patchStrategy, | ||
) (JsonNode, error) { | ||
return patch(jsonString(sori), pathBehind, pathAhead, oldValue, newValue, strategy) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package jd | ||
|
||
import ( | ||
"strings" | ||
"testing" | ||
) | ||
|
||
func TestPatchJsonStringOrInteger(t *testing.T) { | ||
tests := []struct { | ||
a string | ||
b string | ||
diff []string | ||
wantError bool | ||
}{{ | ||
a: `{"0":{}}`, | ||
b: `{"0":{"foo":"bar"}}`, | ||
diff: ss( | ||
`@ ["0", "foo"]`, | ||
`+ "bar"`, | ||
), | ||
}, { | ||
a: `{"0":{}}`, | ||
b: `{"0":{"foo":"bar"}}`, | ||
diff: ss( | ||
`@ [0, "foo"]`, | ||
`+ "bar"`, | ||
), | ||
}, { | ||
a: `[]`, | ||
b: `[1]`, | ||
diff: ss( | ||
`@ ["0"]`, | ||
`+ 1`, | ||
), | ||
}, { | ||
a: `[]`, | ||
b: `[1]`, | ||
diff: ss( | ||
`@ [0]`, | ||
`+ 1`, | ||
), | ||
}} | ||
|
||
for _, tt := range tests { | ||
diffString := strings.Join(tt.diff, "\n") | ||
initial, err := ReadJsonString(tt.a) | ||
if err != nil { | ||
t.Errorf(err.Error()) | ||
} | ||
diff, err := ReadDiffString(diffString) | ||
if err != nil { | ||
t.Errorf(err.Error()) | ||
} | ||
expect, err := ReadJsonString(tt.b) | ||
if err != nil { | ||
t.Errorf(err.Error()) | ||
} | ||
// Coerce to patch format so we'll create a jsonStringOrNumber object when reading the diff. | ||
patchString, err := diff.RenderPatch() | ||
if err != nil { | ||
t.Errorf(err.Error()) | ||
} | ||
patchDiff, err := ReadPatchString(patchString) | ||
if err != nil { | ||
t.Errorf(err.Error()) | ||
} | ||
b, err := initial.Patch(patchDiff) | ||
if tt.wantError && err == nil { | ||
t.Errorf("wanted error but got none") | ||
} | ||
if !tt.wantError && err != nil { | ||
t.Errorf("wanted no error but got %v", err) | ||
} | ||
if !tt.wantError && !expect.Equals(b) { | ||
t.Errorf("%v.Patch(%v) = %v. Want %v.", | ||
tt.a, diffString, b, tt.b) | ||
} | ||
} | ||
|
||
} |