Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions msgp/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,35 @@ func rwMap(dst jsWriter, src *Reader) (n int, err error) {
n++
}

field, err = src.ReadMapKeyPtr()
var kt Type
kt, err = src.NextType()
if err != nil {
return
}
nn, err = rwquoted(dst, field)
switch kt {
case IntType:
var i64 int64
i64, err = src.ReadInt64()
if err != nil {
return
}
src.scratch = strconv.AppendInt(src.scratch[:0], i64, 10)
nn, err = rwquoted(dst, src.scratch)
case UintType:
var u64 uint64
u64, err = src.ReadUint64()
if err != nil {
return
}
src.scratch = strconv.AppendUint(src.scratch[:0], u64, 10)
nn, err = rwquoted(dst, src.scratch)
default:
field, err = src.ReadMapKeyPtr()
if err != nil {
return
}
nn, err = rwquoted(dst, field)
}
n += nn
if err != nil {
return
Expand Down
21 changes: 21 additions & 0 deletions msgp/json_bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,27 @@ func rwMapBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []by
}

func rwMapKeyBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) {
if len(msg) < 1 {
return msg, scratch, ErrShortBytes
}
switch getType(msg[0]) {
case IntType:
i, msg, err := ReadInt64Bytes(msg)
if err != nil {
return msg, scratch, err
}
scratch = strconv.AppendInt(scratch[:0], i, 10)
_, err = rwquoted(w, scratch)
return msg, scratch, err
case UintType:
u, msg, err := ReadUint64Bytes(msg)
if err != nil {
return msg, scratch, err
}
scratch = strconv.AppendUint(scratch[:0], u, 10)
_, err = rwquoted(w, scratch)
return msg, scratch, err
}
msg, scratch, err := rwStringBytes(w, msg, scratch, depth)
if err != nil {
if tperr, ok := err.(TypeError); ok && tperr.Encoded == BinType {
Expand Down
23 changes: 23 additions & 0 deletions msgp/json_bytes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,29 @@ func TestUnmarshalJSON(t *testing.T) {
t.Logf("JSON: %s", js.Bytes())
}

func TestUnmarshalAsJSONNumericMapKeys(t *testing.T) {
var buf bytes.Buffer
enc := NewWriter(&buf)
enc.WriteMapHeader(2)
enc.WriteInt64(-5)
enc.WriteString("neg")
enc.WriteUint64(42)
enc.WriteString("pos")
enc.Flush()

var js bytes.Buffer
if _, err := UnmarshalAsJSON(&js, buf.Bytes()); err != nil {
t.Fatal(err)
}
mp := make(map[string]any)
if err := json.Unmarshal(js.Bytes(), &mp); err != nil {
t.Fatalf("unmarshal: %s — json: %s", err, js.String())
}
if mp["-5"] != "neg" || mp["42"] != "pos" {
t.Errorf("unexpected map: %v", mp)
}
}

func BenchmarkUnmarshalAsJSON(b *testing.B) {
var buf bytes.Buffer
enc := NewWriter(&buf)
Expand Down
23 changes: 23 additions & 0 deletions msgp/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,29 @@ func TestCopyJSON(t *testing.T) {
}
}

func TestCopyJSONNumericMapKeys(t *testing.T) {
var buf bytes.Buffer
enc := NewWriter(&buf)
enc.WriteMapHeader(2)
enc.WriteInt64(-5)
enc.WriteString("neg")
enc.WriteUint64(42)
enc.WriteString("pos")
enc.Flush()

var js bytes.Buffer
if _, err := CopyToJSON(&js, &buf); err != nil {
t.Fatal(err)
}
mp := make(map[string]any)
if err := json.Unmarshal(js.Bytes(), &mp); err != nil {
t.Fatalf("unmarshal: %s — json: %s", err, js.String())
}
if mp["-5"] != "neg" || mp["42"] != "pos" {
t.Errorf("unexpected map: %v", mp)
}
}

// Encoder should generate valid utf-8 even if passed bad input
func TestCopyJSONNegativeUTF8(t *testing.T) {
// Single string with non-compliant utf-8 byte
Expand Down
Loading