Custom UnmarshalJSON not being called

895 views Asked by At

I have an interface that's implemented by a few structs. On one of my methods, I instantiate the struct base on a given string and then parse a json into the defined struct. To do so, I have implemented UnmarshalJSON but it's never being called.

Interface:

type vehicle interface {
    vehicleType() string
    numberOfWheels() int
    EngineType() string
}

Two structs that implement the interface:

type truck struct {
    loadCapacity  int
    capacityUnits string
}

func (t truck) vehicleType() string {
    return "Truck"
}

func (t truck) numberOfWheels() int {
    return 6
}

func (t truck) EngineType() string {
    return "Gasoline"
}

func (t *truck) UnmarshalJSON(data []byte) error {
    fmt.Println("Here in custom unmarshal")
    return nil
}

// -------------------------------------------
type ev struct {
    capacityInKWh int
}

func (e ev) vehicleType() string {
    return "Electric Vehicle"
}

func (e ev) numberOfWheels() int {
    return 4
}

func (e ev) EngineType() string {
    return "Electric"
}

func (e ev) Capacity() int {
    return e.capacityInKWh
}

Notice that my truck struct also implements the custom UnmarshalJSON.

Now, in main I'm trying to do the following:

func main() {
    jsonData := []byte(`{"loadCapacity": 1000, "capacityUnits": "lb"}`)
    vehicleType := "truck"

    processVehicle(vehicleType, jsonData)
}

func processVehicle(vehicleType string, data []byte) {
    var myVehicle vehicle

    fmt.Println("Processing vehicle...")

    switch vehicleType {
    case "truck":
        myVehicle = truck{}
    }

    err := json.Unmarshal(data, &myVehicle)
    if err != nil {
        fmt.Println(err.Error())
        return
    }

    fmt.Println(myVehicle)
}

But I'm getting the following error:

json: cannot unmarshal object into Go value of type main.vehicle

I know there's no actual body in the implemented UnmarshalJSON for truck but I'd expect at least the message to be printed.

What am I doing wrong?

1

There are 1 answers

1
blimzy On

The JSONUnmarshal function is on the pointer receiver. Use a pointer value to access that method.

switch vehicleType {
case "truck":
    myVehicle = &truck{}  // <-- add & here
}

err := json.Unmarshal(data, myVehicle) // <-- & not needed here

Run it on the Go Playground.