Meng Zhuo has uploaded this change for review.
encoding/json: fix invalid kind reflect type
If an invalid value kind calling value type will raise panic which
should not happend.
However it's possible that value implements MarshalText calling by
stringEncoder doesn't check on value kind.
Fixes #43207
Change-Id: If4bc55229b1f64b8ca4b0fed37549725efdace39
---
M src/encoding/json/encode.go
M src/encoding/json/encode_test.go
2 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go
index 483b9d8..cc3e58a 100644
--- a/src/encoding/json/encode.go
+++ b/src/encoding/json/encode.go
@@ -617,6 +617,10 @@
)
func stringEncoder(e *encodeState, v reflect.Value, opts encOpts) {
+ if v.Kind() == reflect.Invalid {
+ e.error(fmt.Errorf("json: invalid kind %q", v))
+ return
+ }
if v.Type() == numberType {
numStr := v.String()
// In Go1.5 the empty string encodes to "0", while this is not a valid number literal
diff --git a/src/encoding/json/encode_test.go b/src/encoding/json/encode_test.go
index 42bb09d..c350a45 100644
--- a/src/encoding/json/encode_test.go
+++ b/src/encoding/json/encode_test.go
@@ -245,6 +245,15 @@
}
}
+// Issue 43207
+func TestUnsupportedKind(t *testing.T) {
+ m := map[textfloat]string{textfloat(math.NaN()): "NaN"}
+ d, err := Marshal(m)
+ if err == nil {
+ t.Errorf("expect err, got nil, d=%s", string(d))
+ }
+}
+
// Ref has Marshaler and Unmarshaler methods with pointer receiver.
type Ref int
@@ -854,6 +863,10 @@
return buf.Bytes(), nil
}
+type textfloat float64
+
+func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) }
+
// Issue 13783
func TestEncodeBytekind(t *testing.T) {
testdata := []struct {
@@ -872,6 +885,7 @@
{[]jsonint{5, 4}, `[{"JI":5},{"JI":4}]`},
{[]textint{9, 3}, `["TI:9","TI:3"]`},
{[]int{9, 3}, `[9,3]`},
+ {[]textfloat{12, 3}, `["TF:12.00","TF:3.00"]`},
}
for _, d := range testdata {
js, err := Marshal(d.data)
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Meng Zhuo.
Patch set 1:Run-TryBot +1
Attention is currently required from: Meng Zhuo.
1 comment:
File src/encoding/json/encode_test.go:
Patch Set #1, Line 252: if err == nil {
Since textfloat implements encoding.TextMarshaler, shouldn't this be a non-error?
(https://play.golang.org/p/ZwHwWxJswCo)
I would expect that the bug is due to an invalid map lookup; encoding/json probably needs to use MapRange instead of MapKeys.¹ See CL 129777 for an example of a corresponding fix in the `fmt` package.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Meng Zhuo.
Meng Zhuo uploaded patch set #2 to this change.
encoding/json: MarshalMap by iteration
The MarshalMap using MapIndex for accessing map value,
Unfortunately it's invalid when underlying type is unsupported but type
has implemented MarshalText interface. i.e.
type A float64
m :=map[A]int{math.NaN(): 1}
As JSON spec(rfc7159) doesn't specified on duplicate objects, we can
encode map with duplicate object with some performance improvement.
name old time/op new time/op delta
MarshalMap/Item=32 0.00ns ±24% 0.00ns ±21% -11.18% (p=0.018 n=9+9)
MarshalMap/Item=64 0.00ns ± 8% 0.00ns ± 8% -8.00% (p=0.002 n=10+10)
MarshalMap/Item=128 0.00ns ± 4% 0.00ns ±20% -8.31% (p=0.010 n=9+9)
MarshalMap/Item=256 0.00ns ± 3% 0.00ns ± 3% -9.28% (p=0.000 n=10+10)
MarshalMap/Item=512 0.00ns ± 1% 0.00ns ±10% -6.59% (p=0.005 n=8+10)
MarshalMap/Item=1024 0.00ns ± 2% 0.00ns ± 4% -8.53% (p=0.000 n=9+9)
MarshalMap/Item=2048 0.00ns ± 2% 0.00ns ± 2% -8.29% (p=0.000 n=9+8)
MarshalMap/Item=4096 0.00ns ± 7% 0.00ns ± 2% -8.82% (p=0.000 n=9+10)
name old alloc/op new alloc/op delta
MarshalMap/Item=32 0.00B 0.00B ~ (all equal)
MarshalMap/Item=64 0.00B 0.00B ~ (all equal)
MarshalMap/Item=128 0.00B 0.00B ~ (all equal)
MarshalMap/Item=256 0.00B 0.00B ~ (all equal)
MarshalMap/Item=512 0.00B 0.00B ~ (all equal)
MarshalMap/Item=1024 0.00B 0.00B ~ (all equal)
MarshalMap/Item=2048 0.00B 0.00B ~ (all equal)
MarshalMap/Item=4096 0.00B 0.00B ~ (all equal)
name old allocs/op new allocs/op delta
MarshalMap/Item=32 0.00 0.00 ~ (all equal)
MarshalMap/Item=64 0.00 0.00 ~ (all equal)
MarshalMap/Item=128 0.00 0.00 ~ (all equal)
MarshalMap/Item=256 0.00 0.00 ~ (all equal)
MarshalMap/Item=512 0.00 0.00 ~ (all equal)
MarshalMap/Item=1024 0.00 0.00 ~ (all equal)
MarshalMap/Item=2048 0.00 0.00 ~ (all equal)
MarshalMap/Item=4096 0.00 0.00 ~ (all equal)
Fixes #43207
Change-Id: If4bc55229b1f64b8ca4b0fed37549725efdace39
---
M src/encoding/json/bench_test.go
M src/encoding/json/encode.go
M src/encoding/json/encode_test.go
3 files changed, 57 insertions(+), 18 deletions(-)
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Bryan C. Mills.
Patch set 2:Run-TryBot +1
1 comment:
File src/encoding/json/encode_test.go:
Patch Set #1, Line 252: if err == nil {
Since textfloat implements encoding.TextMarshaler, shouldn't this be a non-error? […]
Done
We can simply use MapRange instead of MapIndex
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Bryan C. Mills, Joe Tsai.
1 comment:
Patchset:
PING
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
Patch set 2:Run-TryBot +1Code-Review +1Trust +1
1 comment:
File src/encoding/json/encode.go:
Patch Set #2, Line 780: || v.Kind() == reflect.Invalid {
This part of the check should not be needed: `encode` should not be called on an invalid reflect.Value in the first place.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Meng Zhuo, Joe Tsai.
1 comment:
Patchset:
If this is a bug fix, I'm not sure why we're adding a benchmark. Also, I'm confused at all the results saying 0ns.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
1 comment:
Patchset:
If this is a bug fix, I'm not sure why we're adding a benchmark.
I suspect that the benchmark is intended to ensure that the change doesn't introduce a significant performance regression.
Also, I'm confused at all the results saying 0ns.
Ooh, good catch! Looks like the benchmark is forgetting to iterate over b.N.
That would probably also be caught by CL 230978 (see #38677), but that check unfortunately did not make 1.16.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Bryan C. Mills, Meng Zhuo, Joe Tsai.
1 comment:
Patchset:
> If this is a bug fix, I'm not sure why we're adding a benchmark. […]
I get not wanting perf regressions, but I'm sure existing benchmarks already cover maps. I am worried that json is just gaining more micro-benchmarks which don't really help long-term.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Bryan C. Mills, Meng Zhuo, Joe Tsai.
Meng Zhuo uploaded patch set #3 to this change.
encoding/json: MarshalMap by iteration
The MarshalMap using MapIndex for accessing map value,
Unfortunately it's invalid when underlying type is unsupported but type
has implemented MarshalText interface. i.e.
type A float64
m :=map[A]int{math.NaN(): 1}
As JSON spec(rfc7159) doesn't specified on duplicate objects, we can
encode map with duplicate object.
Fixes #43207
Change-Id: If4bc55229b1f64b8ca4b0fed37549725efdace39
---
M src/encoding/json/encode.go
M src/encoding/json/encode_test.go
2 files changed, 40 insertions(+), 17 deletions(-)
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Bryan C. Mills, Daniel Martí, Joe Tsai.
Patch set 3:Run-TryBot +1
3 comments:
Patchset:
I get not wanting perf regressions, but I'm sure existing benchmarks already cover maps. […]
Done
Patchset:
All done and I've removed the benchmark.
File src/encoding/json/encode.go:
Patch Set #2, Line 780: || v.Kind() == reflect.Invalid {
This part of the check should not be needed: `encode` should not be called on an invalid reflect. […]
Done
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
Patch set 3:Code-Review +1
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
Patch set 3:Code-Review +1
9 comments:
Commit Message:
Patch Set #3, Line 7: MarshalMap by iteration
There is no exported function named MarshalMap
Perhaps:
encoding/json: marshal maps using reflect.Value.MapRange
The MarshalMap using MapIndex for accessing map value,
Unfortunately it's invalid when underlying type is unsupported but type
has implemented MarshalText interface. i.e.
Again, there is no MarshalMap function.
Perhaps:
> Map serialization using reflect.Value.MapIndex cannot retrieve map keys that contain a NaN, resulting in a panic. Switch the implementation to use the reflect.Value.MapRange method instead, which iterates over all map entries regardless of whether they are directly retrievable.
Nit: space after :=
As JSON spec(rfc7159) doesn't specified on duplicate objects, we can
encode map with duplicate object.
It *does* actually specify duplicate names, it just specifies that it is implementation specific behavior.
Thus, this should say something like:
> Note that according to RFC 8259, section 4, a JSON object should have unique names, but does not forbid the occurrence of duplicate names.
Also, RFC 7159 has been obsoleted by RFC 8259, so we should use the latter.
Patchset:
Thanks for the fix. Lots of minor comments.
File src/encoding/json/encode_test.go:
s/d/got/
Patch Set #3, Line 256: t.Errorf("err=%v, d=%s", err, string(d))
Style nit:
t.Errorf("Marshal() error: %v", err)Patch Set #3, Line 258: expect
s/expect/want/
if sd := string(d); sd != expect {
t.Errorf("expect=%s, got=%s", expect, sd)
}
Style nit:
if string(got) != want {
t.Errorf("Marshal() = %s, want %s", got, want)
}To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
Meng Zhuo uploaded patch set #4 to this change.
encoding/json: marshal maps using reflect.Value.MapRange
Map serialization using reflect.Value.MapIndex cannot retrieve
map keys that contain a NaN, resulting in a panic.
Switch the implementation to use the reflect.Value.MapRange method
instead, which iterates over all map entries regardless of whether
they are directly retrievable. i.e.
type A float64
m := map[A]int{math.NaN(): 1}
Note that according to RFC 8259, section 4, a JSON object should
have unique names, but does not forbid the occurrence of duplicate names.
Fixes #43207
Change-Id: If4bc55229b1f64b8ca4b0fed37549725efdace39
---
M src/encoding/json/encode.go
M src/encoding/json/encode_test.go
2 files changed, 40 insertions(+), 17 deletions(-)
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Joe Tsai.
9 comments:
Commit Message:
Patch Set #3, Line 7: MarshalMap by iteration
There is no exported function named MarshalMap […]
Done
The MarshalMap using MapIndex for accessing map value,
Unfortunately it's invalid when underlying type is unsupported but type
has implemented MarshalText interface. i.e.
Again, there is no MarshalMap function. […]
Done
Nit: space after :=
Done
As JSON spec(rfc7159) doesn't specified on duplicate objects, we can
encode map with duplicate object.
It *does* actually specify duplicate names, it just specifies that it is implementation specific beh […]
Done
Patchset:
Hi, Joe
Thank you for the review!
All done.
File src/encoding/json/encode_test.go:
s/d/got/
Done
Patch Set #3, Line 256: t.Errorf("err=%v, d=%s", err, string(d))
Style nit: […]
Done
Patch Set #3, Line 258: expect
s/expect/want/
Done
if sd := string(d); sd != expect {
t.Errorf("expect=%s, got=%s", expect, sd)
}
Style nit: […]
Done
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
Bryan C. Mills removed a vote from this change.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
Patch set 4:Code-Review +2Trust +1
1 comment:
Commit Message:
i.e.
type A float64
m := map[A]int{math.NaN(): 1}
This should be "e.g." not "i.e."
You can literally treat "i.e." as "that is"
and treat "e.g." as "for example".
It's one of those weird cases where Latin has entered the English language.
However, this example itself is already incorrect since it you can't natively serialize a float without the MarshalText method, which this doesn't show.
Perhaps:
type F float64
func (f F) MarshalText() ([]byte, error) {
return []byte(fmt.Sprint(f)), nil
}
json.Marshal(map[F]int{math.NaN(): 1}) // should not panic
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
Meng Zhuo uploaded patch set #5 to this change.
encoding/json: marshal maps using reflect.Value.MapRange
Map serialization using reflect.Value.MapIndex cannot retrieve
map keys that contain a NaN, resulting in a panic.
Switch the implementation to use the reflect.Value.MapRange method
instead, which iterates over all map entries regardless of whether
they are directly retrievable.
Note that according to RFC 8259, section 4, a JSON object should
have unique names, but does not forbid the occurrence of duplicate names.
Fixes #43207
Change-Id: If4bc55229b1f64b8ca4b0fed37549725efdace39
---
M src/encoding/json/encode.go
M src/encoding/json/encode_test.go
2 files changed, 40 insertions(+), 17 deletions(-)
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Joe Tsai.
2 comments:
Commit Message:
i.e.
type A float64
m := map[A]int{math.NaN(): 1}
This should be "e.g." not "i.e." […]
Done
Patchset:
Thanks for clear this up.
I think we should remove this example this not very helpful.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Joe Tsai.
1 comment:
Patchset:
Hi, Joe
This CL is a bug, is it OK to merge this CL into Go 1.16?
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
Bryan C. Mills removed a vote from this change.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
1 comment:
Patchset:
Patch Set 5: TryBot-Result-1
1 of 21 TryBots failed:
Failed on android-amd64-emu: https://storage.googleapis.com/go-build-log/0b96ad42/android-amd64-emu_975eb008.logConsult https://build.golang.org/ to see whether they are new failures. Keep in mind that TryBots currently test *exactly* your git commit, without rebasing. If your commit's git parent is old, the failure might've already been fixed.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
Bryan C. Mills removed a vote from this change.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
1 comment:
Patchset:
Hi, Joe […]
I believe Go1.16 is frozen. This will have to wait for Go1.17 to be merged.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Patchset:
I believe Go1.16 is frozen. This will have to wait for Go1.17 to be merged.
Go 1.16 is frozen, but the tree is still open for bug-fixes (which this is, because it causes a panic when the `encoding/json` API is used as documented).
That said, we're very close to the release, so it's not obvious to me whether this change is too invasive for this point in the cycle.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Bryan C. Mills, Daniel Martí, Meng Zhuo, Joe Tsai.
1 comment:
Patchset:
Go 1. […]
This switches map iteration to a different mechanism and may have vastly different performance characteristics. At the very least, we need to benchmark this to understand the impact. I suspect that this will be faster, but we need to prove that.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Bryan C. Mills, Daniel Martí, Joe Tsai.
1 comment:
Patchset:
This switches map iteration to a different mechanism and may have vastly different performance chara […]
Hi, Joe
I've uploaded patchset #2 that contains a benchmark, could you take a look?
name old time/op new time/op delta
MarshalMap/Item=32 0.00ns ±24% 0.00ns ±21% -11.18% (p=0.018 n=9+9)
MarshalMap/Item=64 0.00ns ± 8% 0.00ns ± 8% -8.00% (p=0.002 n=10+10)
MarshalMap/Item=128 0.00ns ± 4% 0.00ns ±20% -8.31% (p=0.010 n=9+9)
MarshalMap/Item=256 0.00ns ± 3% 0.00ns ± 3% -9.28% (p=0.000 n=10+10)
MarshalMap/Item=512 0.00ns ± 1% 0.00ns ±10% -6.59% (p=0.005 n=8+10)
MarshalMap/Item=1024 0.00ns ± 2% 0.00ns ± 4% -8.53% (p=0.000 n=9+9)
MarshalMap/Item=2048 0.00ns ± 2% 0.00ns ± 2% -8.29% (p=0.000 n=9+8)
MarshalMap/Item=4096 0.00ns ± 7% 0.00ns ± 2% -8.82% (p=0.000 n=9+10)
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
1 comment:
Patchset:
Hi, Joe […]
0.00ns/op indicates that the benchmark was not actually using b.N, so those results are probably not valid.
(Even ~10 instructions would be 1.0 ns/op or more.)
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Daniel Martí, Meng Zhuo, Joe Tsai.
Patch set 5:Code-Review +2Trust +1
1 comment:
Patchset:
Go1.16 was just released, so we can submit this for Go1.17.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Meng Zhuo, Joe Tsai.
1 comment:
Patchset:
Bump, Meng. The Gerrit emails were busted last week.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Bryan C. Mills, Joe Tsai.
1 comment:
Patchset:
0.00ns/op indicates that the benchmark was not actually using b. […]
There is no MarshalMap original bench sets. I think we are fine to fix this bug without benchmarks.
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.
Meng Zhuo submitted this change.
encoding/json: marshal maps using reflect.Value.MapRange
Map serialization using reflect.Value.MapIndex cannot retrieve
map keys that contain a NaN, resulting in a panic.
Switch the implementation to use the reflect.Value.MapRange method
instead, which iterates over all map entries regardless of whether
they are directly retrievable.
Note that according to RFC 8259, section 4, a JSON object should
have unique names, but does not forbid the occurrence of duplicate names.
Fixes #43207
Change-Id: If4bc55229b1f64b8ca4b0fed37549725efdace39
Reviewed-on: https://go-review.googlesource.com/c/go/+/278632
Trust: Meng Zhuo <m...@golangcn.org>
Trust: Joe Tsai <thebroke...@gmail.com>
Trust: Bryan C. Mills <bcm...@google.com>
Run-TryBot: Meng Zhuo <m...@golangcn.org>
TryBot-Result: Go Bot <go...@golang.org>
Reviewed-by: Joe Tsai <thebroke...@gmail.com>
Reviewed-by: Daniel Martí <mv...@mvdan.cc>
---
M src/encoding/json/encode.go
M src/encoding/json/encode_test.go
2 files changed, 40 insertions(+), 17 deletions(-)
diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go
index 751f03d..e473e61 100644
--- a/src/encoding/json/encode.go
+++ b/src/encoding/json/encode.go
@@ -794,23 +794,24 @@
e.WriteByte('{')
// Extract and sort the keys.
- keys := v.MapKeys()
- sv := make([]reflectWithString, len(keys))
- for i, v := range keys {
- sv[i].v = v
+ sv := make([]reflectWithString, v.Len())
+ mi := v.MapRange()
+ for i := 0; mi.Next(); i++ {
+ sv[i].k = mi.Key()
+ sv[i].v = mi.Value()
if err := sv[i].resolve(); err != nil {
e.error(fmt.Errorf("json: encoding error for type %q: %q", v.Type().String(), err.Error()))
}
}
- sort.Slice(sv, func(i, j int) bool { return sv[i].s < sv[j].s })
+ sort.Slice(sv, func(i, j int) bool { return sv[i].ks < sv[j].ks })
for i, kv := range sv {
if i > 0 {
e.WriteByte(',')
}
- e.string(kv.s, opts.escapeHTML)
+ e.string(kv.ks, opts.escapeHTML)
e.WriteByte(':')
- me.elemEnc(e, v.MapIndex(kv.v), opts)
+ me.elemEnc(e, kv.v, opts)
}
e.WriteByte('}')
e.ptrLevel--
@@ -997,29 +998,30 @@
}
type reflectWithString struct {
- v reflect.Value
- s string
+ k reflect.Value
+ v reflect.Value
+ ks string
}
func (w *reflectWithString) resolve() error {
- if w.v.Kind() == reflect.String {
- w.s = w.v.String()
+ if w.k.Kind() == reflect.String {
+ w.ks = w.k.String()
return nil
}
- if tm, ok := w.v.Interface().(encoding.TextMarshaler); ok {
- if w.v.Kind() == reflect.Ptr && w.v.IsNil() {
+ if tm, ok := w.k.Interface().(encoding.TextMarshaler); ok {
+ if w.k.Kind() == reflect.Ptr && w.k.IsNil() {
return nil
}
buf, err := tm.MarshalText()
- w.s = string(buf)
+ w.ks = string(buf)
return err
}
- switch w.v.Kind() {
+ switch w.k.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- w.s = strconv.FormatInt(w.v.Int(), 10)
+ w.ks = strconv.FormatInt(w.k.Int(), 10)
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- w.s = strconv.FormatUint(w.v.Uint(), 10)
+ w.ks = strconv.FormatUint(w.k.Uint(), 10)
return nil
}
panic("unexpected map key type")
diff --git a/src/encoding/json/encode_test.go b/src/encoding/json/encode_test.go
index 42bb09d..0dad951 100644
--- a/src/encoding/json/encode_test.go
+++ b/src/encoding/json/encode_test.go
@@ -245,6 +245,22 @@
}
}
+// Issue 43207
+func TestMarshalTextFloatMap(t *testing.T) {
+ m := map[textfloat]string{
+ textfloat(math.NaN()): "1",
+ textfloat(math.NaN()): "1",
+ }
+ got, err := Marshal(m)
+ if err != nil {
+ t.Errorf("Marshal() error: %v", err)
+ }
+ want := `{"TF:NaN":"1","TF:NaN":"1"}`
+ if string(got) != want {
+ t.Errorf("Marshal() = %s, want %s", got, want)
+ }
+}
+
// Ref has Marshaler and Unmarshaler methods with pointer receiver.
type Ref int
@@ -854,6 +870,10 @@
return buf.Bytes(), nil
}
+type textfloat float64
+
+func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) }
+
// Issue 13783
func TestEncodeBytekind(t *testing.T) {
testdata := []struct {
@@ -872,6 +892,7 @@
{[]jsonint{5, 4}, `[{"JI":5},{"JI":4}]`},
{[]textint{9, 3}, `["TI:9","TI:3"]`},
{[]int{9, 3}, `[9,3]`},
+ {[]textfloat{12, 3}, `["TF:12.00","TF:3.00"]`},
}
for _, d := range testdata {
js, err := Marshal(d.data)
To view, visit change 278632. To unsubscribe, or for help writing mail filters, visit settings.