解组不带结构的未知JSON字段

I am trying to unmarshal a JSON object which has an optional array, I am doing this without an array and this is what I got so far:

import (
    "encoding/json"
    "fmt"
)

func main() {

    jo := `
        {
            "given_name": "Akshay Raj",
            "name": "Akshay",
            "country": "New Zealand",
            "family_name": "Gollahalli",
            "emails": [
                "name@example.com"
                ]
        }
        `
    var raw map[string]interface{}
    err := json.Unmarshal([]byte(jo), &raw)
    if err != nil {
        panic(err)
    }

    fmt.Println(raw["emails"][0])

}

The emails field might or might not come sometime. I know I can use struct and unmarshal it twice for with and without array. When I try to get the index 0 of raw["emails"][0] I get the following error

invalid operation: raw["emails"][0] (type interface {} does not support indexing)

Is there a way to get the index of the emails field?

Update 1

I can do something like this fmt.Println(raw["emails"].([]interface{})[0]) and it works. Is this the only way?

The easiest way is with a struct. There's no need to unmarshal twice.

type MyStruct struct {
    // ... other fields
    Emails []string `json:"emails"`
}

This will work, regardless of whether the JSON input contains the emails field. When it is missing, your resulting struct will just have an uninitialized Emails field.

You can use type assertions. The Go tutorial on type assertions is here.

A Go playground link applying type assertions to your problem is here. For ease of reading, that code is replicated below:

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    jo := `
        {
            "given_name": "Akshay Raj",
            "name": "Akshay",
            "country": "New Zealand",
            "family_name": "Gollahalli",
            "emails": [
                "name@example.com"
            ]
        }
        `
    var raw map[string]interface{}
    err := json.Unmarshal([]byte(jo), &raw)
    if err != nil {
        panic(err)
    }

    emails, ok := raw["emails"]
    if !ok {
        panic("do this when no 'emails' key")
    }

    emailsSlice, ok := emails.([]interface{})
    if !ok {
        panic("do this when 'emails' value is not a slice")
    }

    if len(emailsSlice) == 0 {
        panic("do this when 'emails' slice is empty")
    }

    email, ok := (emailsSlice[0]).(string)
    if !ok {
        panic("do this when 'emails' slice contains non-string")
    }

    fmt.Println(email)

}

As always you can use additional libraries for work with your json data. For example with gojsonq package it will like so:

package main

import (
    "fmt"

    "github.com/thedevsaddam/gojsonq"
)

func main() {

    json := `
        {
            "given_name": "Akshay Raj",
            "name": "Akshay",
            "country": "New Zealand",
            "family_name": "Gollahalli",
            "emails": [
                "name@example.com"
                ]
        }
        `
    first := gojsonq.New().JSONString(json).Find("emails.[0]")
    if first != nil {
        fmt.Println(first.(string))
    } else {
        fmt.Println("There isn't emails")
    }

}