Unmarshal неизвестные поля JSON без структур - PullRequest
0 голосов
/ 06 июля 2019

Я пытаюсь демонтировать JSON-объект, который имеет необязательный массив, я делаю это без массива, и вот что я получил до сих пор:

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])

}

Поле emails может или не можетне придет когда-нибудь.Я знаю, что могу использовать struct и разархивировать его дважды для массива и без него.Когда я пытаюсь получить индекс 0 из raw["emails"][0], я получаю следующую ошибку

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

Можно ли получить индекс поля emails?

Обновление 1

Я могу сделать что-то вроде этого fmt.Println(raw["emails"].([]interface{})[0]), и это работает.Это единственный способ?

Ответы [ 3 ]

4 голосов
/ 06 июля 2019

Самый простой способ - с помощью структуры.Нет необходимости дважды демаршировать.

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

Это будет работать независимо от того, содержит ли вход JSON поле emails.Если оно отсутствует, ваша результирующая структура будет просто иметь неинициализированное поле Emails.

1 голос
/ 06 июля 2019

Вы можете использовать утверждения типа. Учебник Go по утверждениям типа: здесь .

Ссылка на игровую площадку Go с утверждениями типа для вашей проблемы: здесь . Для удобства чтения этот код воспроизведен ниже:

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)

}
0 голосов
/ 06 июля 2019

Как всегда, вы можете использовать дополнительные библиотеки для работы с данными JSON. Например, с пакетом gojsonq это будет выглядеть так:

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")
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...