Skip to content

Commit 760fbd0

Browse files
Merge pull request #221 from danielgtaylor/fix-gron
fix: gron output with special chars
2 parents 2c85909 + 98245d9 commit 760fbd0

File tree

3 files changed

+23
-23
lines changed

3 files changed

+23
-23
lines changed

cli/content.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ func (t Gron) Detect(contentType string) bool {
263263

264264
// Marshal the value to a gron string.
265265
func (t Gron) Marshal(value interface{}) ([]byte, error) {
266-
pb := NewPathBuffer([]byte("body"), 4)
266+
pb := NewPathBuffer([][]byte{[]byte("body")})
267267
out := make([]byte, 0, 1024)
268268
return marshalGron(pb, value, false, out)
269269
}

cli/gron.go

+13-22
Original file line numberDiff line numberDiff line change
@@ -12,41 +12,30 @@ import (
1212
"unicode"
1313
)
1414

15-
// PathBuffer is a low-allocation helper for building a path string like
16-
// `foo.bar[2].baz`. It is not goroutine-safe, but the underlying buffer can
17-
// be re-used within the same goroutine or via a `sync.Pool`.
15+
// PathBuffer builds up a path string from multiple parts.
1816
type PathBuffer struct {
19-
buf []byte
20-
off int
17+
parts [][]byte
2118
}
2219

2320
func (b *PathBuffer) Push(s string) {
24-
if b.off > 0 && s[0] != '[' {
25-
b.buf = append(b.buf, '.')
26-
b.off++
21+
if s[0] != '[' {
22+
s = "." + s
2723
}
28-
b.buf = append(b.buf, s...)
29-
b.off += len(s)
24+
b.parts = append(b.parts, []byte(s))
3025
}
3126

3227
func (b *PathBuffer) Pop() {
33-
for b.off > 0 {
34-
b.off--
35-
if b.buf[b.off] == '.' || b.buf[b.off] == '[' {
36-
break
37-
}
38-
}
39-
b.buf = b.buf[:b.off]
28+
b.parts = b.parts[:len(b.parts)-1]
4029
}
4130

4231
func (b *PathBuffer) Bytes() []byte {
43-
return b.buf[:b.off]
32+
return bytes.Join(b.parts, []byte{})
4433
}
4534

46-
// NewPathBuffer creates a new path buffer with the given underlying byte slice
47-
// and offset within that slice (for pre-loading with some path data).
48-
func NewPathBuffer(buf []byte, offset int) *PathBuffer {
49-
return &PathBuffer{buf: buf, off: offset}
35+
// NewPathBuffer creates a new path buffer with the given underlying initial
36+
// data loaded into it.
37+
func NewPathBuffer(parts [][]byte) *PathBuffer {
38+
return &PathBuffer{parts: parts}
5039
}
5140

5241
// validFirstRune returns true for runes that are valid
@@ -72,6 +61,8 @@ func identifier(s string) string {
7261
return s
7362
}
7463

64+
s = strings.ReplaceAll(s, `"`, `\"`)
65+
7566
return fmt.Sprintf(`["%s"]`, s)
7667
}
7768

cli/gron_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ func TestGronMarshal(t *testing.T) {
2929
{"e": "world & i <3 restish"},
3030
{"f": []any{1, 2}, "g": time.Time{}, "h": []byte("foo")},
3131
{"for": map[int]int{1: 2}},
32+
{"dotted.name": "foo"},
33+
{"name[with]brackets": "bar"},
34+
{"name\"with": "quote"},
3235
}},
3336
private: true,
3437
}
@@ -52,6 +55,12 @@ body.d[1].h = "Zm9v";
5255
body.d[2] = {};
5356
body.d[2].for = {};
5457
body.d[2].for["1"] = 2;
58+
body.d[3] = {};
59+
body.d[3]["dotted.name"] = "foo";
60+
body.d[4] = {};
61+
body.d[4]["name[with]brackets"] = "bar";
62+
body.d[5] = {};
63+
body.d[5]["name\"with"] = "quote";
5564
`, string(b))
5665

5766
// Invalid types should result in an error!

0 commit comments

Comments
 (0)