encoding/json: custom unmarshaler is ignored for map #34437
Comments
This sounds related to @mvdan's last comment on a similar issue: #28189 (comment) In this case, var m MyString
v := reflect.ValueOf(m)
fmt.Println(v.Kind()) // string
// Even though MyString implements a custom TextUnmarshaler, the ValueOf.Kind check is used first.
var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
p1 := make(map[MyString]string)
v2 := reflect.ValueOf(p1)
fmt.Println(reflect.PtrTo(v2.Type().Key()).Implements(textUnmarshalerType)) // true See related code here: go/src/encoding/json/decode.go Lines 633 to 637 in dfbc9c8 And here: go/src/encoding/json/decode.go Lines 776 to 777 in dfbc9c8 Because the string key case is checked first, your custom As a workaround, you can define a custom map type that defines UnmarshalJSON and does the work you want, but it will not be as clean as you expect in your example. I'll let the domain experts take over from here. |
Playing around with var m MyString
var x string
fmt.Println(reflect.ValueOf(m).Type().Name()) // returns "MyString"
fmt.Println(reflect.ValueOf(x).Type().Name()) // returns "string" It could be a bit hacky ... |
I'm pretty sure this is working as intended:
Note that it mentions |
@mvdan thanks for pointing out the doc. However, it doesn't seem working per the below code. package main
import (
"encoding/json"
"fmt"
"strings"
)
type MyString string
func (m *MyString) UnmarshalText(text []byte) error {
fmt.Println("not invoked")
*m = MyString(strings.ToLower(string(text)))
return nil
}
func main() {
var p map[MyString]string
_ = json.Unmarshal([]byte(`
{
"KEY1": "1",
"KEY2": "2"
}
`), &p)
fmt.Println(p) // INCORRECT output: map[KEY1:1 KEY2:2] but expected: map[key1:1 key2:2]
} Am i missing anything? |
The problem is that
Even |
Change https://golang.org/cl/200237 mentions this issue: |
If i use a custom type for
string
implementingUnmarshaler
interface and use it as key type in a map, the unmarshaling seems not working as expected.The text was updated successfully, but these errors were encountered: