Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested properties for structs with unknown property names?

Tags:

go

I'm using JSON to get some values into a variable from an external source.

I have a type like this that json.Unmarshal puts values into:

    type Frame struct {
        Type  string
        Value map[string]interface{}
    }

    var data Frame

After unmarshal, I can access a the type by: data.Type

but if I try doing something like:

    if data.Type == "image" {
        fmt.Printf("%s\n", data.Value.Imagedata)
    }

The compiler complains about no such value data.Value.Imagedata.

So my question is, how do I reference properties in Go that I know will be there depending on some condition?

Doing this works:

    type Image struct {
        Filename string
    }

    type Frame struct {
        Type  string
        Value map[string]interface{}
    }

But that isn't very flexible as I will be receiving different Values.

like image 312
Senica Gonzalez Avatar asked Mar 21 '12 08:03

Senica Gonzalez


1 Answers

json.Unmarshal will do its best to place the data where it best aligns with your type. Technically your first example will work, but you are trying to access the Value field with dot notation, even though you declared it to be a map:

This should give you some form of output:

if data.Type == 'image'{
    fmt.Printf("%v\n", data.Value["Imagedata"])
}

… considering that "Imagedata" was a key in the JSON.

You have the option of defining the type as deeply as you want or expect the structure to be, or using an interface{} and then doing type assertions on the values. With the Value field being a map, you would always access the keys like Value[key], and the value of that map entry is an interface{} which you could type assert like Value[key].(float64).

As for doing more explicit structures, I have found that you could either break up the objects into their own types, or define it nested in one place:

Nested (with anonymous struct)

type Frame struct {
    Type  string
    Value struct {
        Imagedata string `json:"image_data"`
    }
}

Seperate structs

type Frame struct {
    Type    string
    Value   value 
}

type value struct {
    Imagedata string `json:"image_data"`
}

I'm still learning Go myself, so this the extent of my current understanding :-).

like image 138
jdi Avatar answered Sep 28 '22 03:09

jdi