encoding/json doesn't find marshal/unmarshal via type aliases

442 views
Skip to first unread message

Marcin Romaszewicz

unread,
May 20, 2022, 3:28:55 AM5/20/22
to golang-nuts
Hi All,

I've created a simple struct that wraps time.Time because I'd like to unmarshal it differently from JSON than the default. It works great.

However, when I pass a type alias of that struct to json.Marshal or json.Unmarshal, the MarshalJSON and UnmarshalJSON functions aren't invoked, despite both types conforming to the interfaces.

Here's the shortest example I could make.
I did find a workaround, in redeclaring the MarshalJSON/UnmarshalJSON on the aliased type, but I don't understand why this is necessary, and I'm hoping someone who understands the innards of this better than I do could enlighten me.

Thanks,
-- Marcin


Axel Wagner

unread,
May 20, 2022, 3:36:18 AM5/20/22
to Marcin Romaszewicz, golang-nuts
It's not an "aliased type". Type aliases take the form
type A = B
and they make the name A be interchangeable with the name B. What you have is a type declaration
type A B
which creates a fully new type, with a new method set, but the same underlying type as B.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CA%2Bv29LuOa9sHFWxPxqYq_HtiQZ6_pUhCtMUOAL8Yq1X_UvyjJw%40mail.gmail.com.

Marcin Romaszewicz

unread,
May 20, 2022, 10:14:35 AM5/20/22
to Axel Wagner, golang-nuts
Sorry about mixing up terms, however, my question still stands.

encoding/json looks for the Marshaler/Unmarshaler interface convertibility, and in this case, the compiler thinks that the redeclared type does implement json.Unmarshaler. I extended my example to also do this test via reflection.

https://go.dev/play/p/TrxM2zxG2pX

So, yes, it's a new type, but it seems to behave just like the base type.

Sean Liao

unread,
May 20, 2022, 10:37:39 AM5/20/22
to golang-nuts
As explained above, `type AliasedDate Date` clears any methods you have defined on `Date`.
But `Date` embeds `time.Time` which has its own `UnmrshalJSON`,
which now gets promoted.

So `Date.UnmsrshalJSON` calls your `UnmsrshalJSON`
`AliastedDate.UnmsrshalJSON` calls `AliastedDate.Time.UnmsrshalJSON`

Marcin Romaszewicz

unread,
May 20, 2022, 10:51:47 AM5/20/22
to Sean Liao, golang-nuts
Aha! That is what I was missing. Thank you.

Reply all
Reply to author
Forward
0 new messages