Description
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (go version
)?
version 1.9
Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (go env
)?
windows/amd64
What did you do?
package main
import (
"encoding/json"
"os"
)
type T bool
func (v *T) MarshalJSON() ([]byte, error) {
return []byte{'1'}, nil
}
type S struct {
X T
}
func main() {
v := S{true}
e := json.NewEncoder(os.Stderr)
e.Encode(v) // should print {"X":true}
e.Encode(&v) // should print the same value
}
What did you expect to see?
{"X":true}
{"X":true}
What did you see instead?
{"X":true}
{"X":1}
Issue
The json.Marshal
documentation states that:
Pointer values encode as the value pointed to. A nil pointer encodes as the null JSON value.
Thus, &v
should be marshaled to the same JSON value as v
:
{"X":true}
Moreover, it states that:
If an encountered value implements the Marshaler interface and is not a nil pointer, Marshal calls its MarshalJSON method to produce JSON.
Therefore, Marshal should not call the MarshalJSON
method to produce JSON for the X
field, because its T
type does not implement the json.Marshaler
interface. In fact, MarshalJSON
has *T
receiver and the Go documentation states:
The method set of an interface type is its interface. The method set of any other type
T
consists of all methods declared with receiver typeT
. ... The method set of a type determines the interfaces that the type implements ...
As a final remark:
-
from the source code, the most relevant difference between cases
v
and&v
is thatX
field becomes addressable in case&v
, changing the encoding generated bycondAddrEncoder
; -
implementing
MarshalJSON
withT
value receiver makesT
ajson.Marshaler
interface, withX
values properly encoded by MarshalJSON:{"X":1} {"X":1}
-
if the intended behavior is that Marshal should anyway call the
MarshalJSON
method on encodingT
values, whenever*T
implements thejson.Marshaler
interface, that should be clearly documented.