Home > Back-end >  Representing a list of things of different type in JSON and Golang
Representing a list of things of different type in JSON and Golang

Time:05-28

I'm trying to represent some data in JSON where there is a list of things where each thing has some common features (ex name) and another field who's value can either be a string or an integer. For example:

{
    "items": [
        {
            "name": "thing1",
            "type": "string",
            "value": "foo"
        },
        {
            "name": "thing2",
            "type": "int",
            "value": 42
        }
    ]
}

That JSON looks reasonable to me, but trying to create a data structure to deserialize (unmarshal) it into in Golang is proving difficult. I think I could do it in Java with class polymorphism, but in Go I feel trapped. I've tried many things but haven't got it. Ultimately, it comes down to lack of struct type polymorphism.

In Go, I can have a slice (list) of interfaces, but I need actual structs of different types as far as I can tell.

Any suggestions on how to represent this in Golang, and be able to unmarshal into?

Or alternatively, should I structure the JSON itself differently?

Thanks!

CodePudding user response:

You can create a structure like this

type items struct {
    name   string
    type_1 string
    value  interface{}
}

Interface can hold any data type, also as type is reserved keyword i have used type_1

CodePudding user response:

This data structure properly represents your JSON:

type Data struct {
    Items []struct {
        Name string `json:"name"`
        Type string `json:"type"`
        Value interface{} `json:"value"`
    } `json:"items"`
}

Then, you can use json.Unmarshall. If you use Go 1.18, you can use any alias of interface{}.

In addition, in Go you don't even need a type field. You can use Type assertions to determine the value type.

CodePudding user response:

You can do it in Go 1.18 like this:

type Data struct {
    Items []struct {
        Name string `json:"name"`
        Type string `json:"type"`
        Value any `json:"value"`
    } `json:"items"`
}

func main() {
    data := Data{}

    // it's your json bytes
    bytesData := []byte()

    if err := json.Unmarshal(byteData, &data); err != nil {
        log.Fatal(err)
    }
}

// use data here 

P.S. if you are using older versions use interface{} instead of any.

  • Related