Ключ JSON может быть строкой или объектом

Я хочу разобрать JSON, но один ключ - это либо строка, либо объект.

Вот моя текущая структура: https://github.com/PhillippOhlandt/pmtoapib/blob/master/CollectionItemRequest.go#L10

type CollectionItemRequest struct {
    Url         string          `json:"url"`
    Method      string          `json:"method"`
    Header      []RequestHeader `json:"header"`
    Body        RequestBody     `json:"body"`
    Description string          `json:"description"`
}

Здесь атрибутом «Url» может быть не только строка, но и объект.

Я начал создавать для него собственную структуру, охватывающую случай объекта.

type CollectionItemRequestUrl struct {
    Raw string `json:"raw"`
}

type CollectionItemRequest struct {
    Url         CollectionItemRequestUrl `json:"url"`
    Method      string                   `json:"method"`
    Header      []RequestHeader          `json:"header"`
    Body        RequestBody              `json:"body"`
    Description string                   `json:"description"`
}

Но тогда строковая версия больше не будет работать. Есть ли способ, чтобы оба случая работали и получали значение через геттер, например request.Url.Get?

РЕДАКТИРОВАТЬ:

Вот две версии JSON:

    "request": {
        "url": {
            "raw": "http://localhost:8081/users?per_page=5&page=2",
            "protocol": "http",
            "host": [
                "localhost"
            ],
            "port": "8081",
            "path": [
                "users"
            ],
            "query": [
                {
                    "key": "per_page",
                    "value": "5",
                    "equals": true,
                    "description": ""
                },
                {
                    "key": "page",
                    "value": "2",
                    "equals": true,
                    "description": ""
                }
            ],
            "variable": []
        },

А также

"request": {
                "url": "http://localhost:8081/users/2",

Примечание. Только подмножества, весь JSON будет слишком длинным.


person Phillipp    schedule 17.01.2018    source источник
comment
Покажите примеры JSON.   -  person Cerise Limón    schedule 17.01.2018
comment
Дубликаты обрабатывают гораздо более простые случаи, когда существуют разные типы объектов или целое число / строка и т. Д. Но не строка / объект в большой вложенной структуре.   -  person Phillipp    schedule 17.01.2018
comment
@Cerise Limón Я добавил примеры JSON   -  person Phillipp    schedule 17.01.2018
comment
@Phillipp Некоторые ответы на вопросы, связанные с @JimB, должны сработать для вас. В частности, в этом случае должна работать структура с функцией UnmarshalJSON.   -  person Tulir    schedule 17.01.2018


Ответы (1)


Имейте тип, который имеет настраиваемый метод демаршалирования, который сначала демаршалируется в пустой интерфейс, а затем выполняет переключение типа в зависимости от того, получил ли он string или map[string]interface{}, например:

type example struct {
    URL myURL `json:"url"`
}

type myURL struct {
    url string
}

func (u *myURL) MarshalJSON() ([]byte, error) {
    return json.Marshal(u.url)
}

func (u *myURL) UnmarshalJSON(data []byte) error {
    var raw interface{}
    json.Unmarshal(data, &raw)
    switch raw := raw.(type) {
    case string:
        *u = myURL{raw}
    case map[string]interface{}:
        *u = myURL{raw["raw"].(string)}
    }
    return nil
}

const myStringURL string = `{"url": "http://www.example.com/as-string"}`
const myNestedURL string = `{"url": {"raw": "http://www.example.com/as-nested"}}`

func main() {
    var stringOutput example
    json.Unmarshal([]byte(myStringURL), &stringOutput)
    fmt.Println(stringOutput)

    var nestedOutput example
    json.Unmarshal([]byte(myNestedURL), &nestedOutput)
    fmt.Println(nestedOutput)
}

Здесь можно запустить на игровой площадке:

https://play.golang.org/p/I6KC4aXHpxm

person Iain Duncan    schedule 17.01.2018
comment
Спасибо, работает! Я уже был на правильном пути с методом UnmarshalJSON , но у меня были некоторые проблемы с присвоением значения. - person Phillipp; 17.01.2018