Strange custom json unmarshal behavior using Alias method for nested structs

Came across this blog Custom JSON Marshalling in Go · Choly's Blog that uses Alias to Unmarshal a struct (and avoiding recursion)… but when i tried a similar method with nested structs (with their own Unmarshal()) it no longer works. See code below.

it seems that the Alias of the “derived” struct (BS) is recognised as AS and hence AS.Unmarshal() is called, but subsequent fields are not Unmarshalled. I would really like to understand why.

I noticed that if i included another struct in type BS { AS; CS; Name string} and CS has it’s on Unmarshal(), the code works. If however, CS does not have it’s own Unmarshal(), it doesn’t update CS’s values or the Name field

package main

import (
   "encoding/json"
   "fmt"
)

type AS struct{ Id int }

func (as *AS) UnmarshalJSON(data []byte) error {
   type Alias AS
   aux := struct{ *Alias }{Alias: (*Alias)(as)}

   if err := json.Unmarshal(data, &aux); err != nil {
      return err
   }
   return nil
}

type BS struct {
   AS
   Name string 
}

func (bs *BS) UnmarshalJSON(data []byte) error {
   type Alias BS
   aux := struct{ *Alias }{Alias: (*Alias)(bs)}

   if err := json.Unmarshal(data, &aux); err != nil {
      return err
   }
   return nil
}

func main() {
   bs := BS{}
   data := []byte(`{"id": 10, "name": "TEST ME"}`)
   if err := json.Unmarshal(data, &bs); err != nil {
      panic(err)
   }

   fmt.Printf("bs: %#v\n", bs)
   // Correct result WITHOUT AS.UnmarshalJSON() - e.g by changing the method's name
   // output without AS.UnmarshalJSON() : bs: main.BS{AS:main.AS{Id:10}, Name:"TEST ME"}

   // Wrong result with AS.UnmarshalJSON()
   // output : bs: main.BS{AS:main.AS{Id:10}, Name:""}
   // seems like it only calls AS.UnmarshalJSON() and subsequent fields are not unmarshalled
}

i would really like to understand why?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.