Search code examples
jsongostructmarshallingunmarshalling

Unmarshall should return error when having wrong json input structure


I have struct A and B. When a JSON string A is unmarshalled to struct A then it is valid, however if the JSON string A is unmarshalled to struct B it is still successful (which should not).

Is there any way to detect that wrong JSON input has been wrongly converted to a wrong struct type?

Please look at the code below: play

package main

import (
    "encoding/json"
    "fmt"
)

type A struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

type B struct {
    Alamat string `json:"alamat"`
    Umur   int    `json:"umur"`
}

func main() {
    var structA A
    var structAA A

    valA := "{\"name\":\"budi\",\"age\":10}"
    valB := "{\"alamat\":\"jakarta\",\"umur\":120}"

    //correct case
    err := json.Unmarshal([]byte(valA), &structA)
    if err != nil {
        fmt.Println("fail unmarshal")
    }

    fmt.Println(structA.Name)
    fmt.Println(structA.Age)

    //unmarshalled successfully but with wrong json
    err = json.Unmarshal([]byte(valB), &structAA)
    if err != nil {
        fmt.Println("fail unmarshal")
    }

    fmt.Println(structAA.Name)
    fmt.Println(structAA.Age)

}

Solution

  • Referring the docs, json.Unmarshal(data []byte, v interface{}), by default, does not work in the way you suppose:

    By default, object keys which don't have a corresponding struct field are ignored (see Decoder.DisallowUnknownFields for an alternative).

    So, JSON properties alamat and umur in your valB are ignored as they are not matched in struct A and name and age are set to their type default.