Use of NoMethod type for custom marshaling

73 views
Skip to first unread message

Sathish VJ

unread,
Sep 14, 2019, 4:43:53 AM9/14/19
to golang-nuts
I saw some code where there is a temporary type called noMethod created before performing custom marshaling.

What is the purpose of doing this?  

type T struct {
 A
int
 C
string
}


func
(t T) MarshalText() (text []byte, err error) {
 type noMethod T
 
return json.Marshal(noMethod(t))
}


func
(t *T) UnmarshalText(text []byte) error {
 type noMethod T
 
return json.Unmarshal(text, (*noMethod)(t))
}


func
(t T) MarshalJSON() (text []byte, err error) {
 type noMethod T
 
return json.Marshal(noMethod(t))
}


func
(t *T) UnmarshalJSON(text []byte) error {
 type noMethod T
 
return json.Unmarshal(text, (*noMethod)(t))
}





Ben Burwell

unread,
Sep 14, 2019, 10:50:49 AM9/14/19
to Sathish VJ, golang-nuts
On Sat Sep 14, 2019 at 1:43 AM Sathish VJ wrote:
> I saw some code where there is a temporary type called *noMethod* created
> before performing custom marshaling.
>
> What is the purpose of doing this?
>
> type T struct {
> A int
> C string
> }
>
> func (t T) MarshalJSON() (text []byte, err error) {
> type noMethod T
> return json.Marshal(noMethod(t))
> }
>
> https://play.golang.org/p/e8cZfkU1uvE

When json.Marshal is called, if the value passed implements
json.Marshaler, then that method is called to marshal the value.

If you wrote

func (t T) MarshalJSON() (text []byte, err error) {
return json.Marshal(t)
}

func main() {
var t T
json.Marshal(t)
}

then you'd end up with infinite recursion, as the T.MarshalJSON() method
would just keep getting called. By defining `type noMethod T` and
casting t to a noMethod before calling json.Marshal, you can avoid this
because the noMethod type has, well, no methods, and thus does not
implement json.Marshaler and will be encoded using the struct encoder.

In this case, you may as well just not implement json.Marshaler at all
and fall through immediately to the struct encoder, but perhaps there's
some reason to do this that your example doesn't show.

Sathish VJ

unread,
Sep 15, 2019, 1:26:06 AM9/15/19
to golang-nuts
Yes, that makes sense.  Thank you.

The example I wrote was concocted.  But I've seen others do it on their own types too, which didn't make sense at all.  Maybe they were just copy-pasting similar code from elsewhere.

Jake Montgomery

unread,
Sep 15, 2019, 12:00:16 PM9/15/19
to golang-nuts
On Sunday, September 15, 2019 at 1:26:06 AM UTC-4, Sathish VJ wrote:
Yes, that makes sense.  Thank you.

The example I wrote was concocted.  But I've seen others do it on their own types too, which didn't make sense at all.  Maybe they were just copy-pasting similar code from elsewhere.

If that is the case, then it is a textbook case of Cargo Cult Programming on their part. I applaud you for trying to understand the why.
Reply all
Reply to author
Forward
0 new messages