Unmarshal JSON в зависимости от ключа - PullRequest
0 голосов
/ 25 января 2019

Я получаю данные в формате JSON из сети, и мне нужно разархивировать их в зависимости от ключа.
Вот пример данных:

{
  "foo": {
    "11883920": {
      "fieldA": 123,
      "fieldB": [
        {
          "fieldC": "a",
          "fieldD": 1173653.22
        }
      ]
    }
  },
  "bar": {
     "123": {
       "fieldE": 123
     }
   }
  "anyOtherkey": {...}
}

Логика заключается в том, что если ключ foo, он может быть расшифрован как fooStruct, а если bar - как barStruct. Каков наилучший способ реализовать эту логику? (Я не хочу отменять маршалинг до map[string]interface{}, возможно, это возможно с помощью функции json.NewDecoder(), но я не смог получить ожидаемый результат).

1 Ответ

0 голосов
/ 25 января 2019

Просто создайте тип с обоими присутствующими полями:

type MyType struct {
    Foo      *fooStruct `json:"foo,omitempty"`
    Bar      *barStruct `json:"bar,omitempty"`
    OtherKey string     `json:"other_key"`
}

Распакуйте JSON в этот тип и просто проверьте, что ig Foo и или Bar равны нулю, чтобы знать, с какими данными вы работаетес.

Вот игровая площадка Демонстрация того, на что это будет похоже

Суть этого:

type Foo struct {
    Field int `json:"field1"`
}

type Bar struct {
    Message string `json:"field2"`
}

type Payload struct {
    Foo   *Foo   `json:"foo,omitempty"`
    Bar   *Bar   `json:"bar,omitempty"`
    Other string `json:"another_field"`
}

Foo иBar поля являются типами указателей, потому что поля значений сделают его немного более громоздким, чтобы определить, какое поле было фактически установлено.Бит omitempty позволяет вам маршалировать тот же тип, чтобы воссоздать исходную полезную нагрузку, поскольку значения nil просто не будут отображаться в выходных данных.

Чтобы проверить, какое поле было установлено в исходной строке JSON,просто напишите:

var data Payload
if err := json.Unmarshal([]byte(jsonString), &data); err != nil {
    // handle error
}
if data.Foo == nil && data.Bar == nil {
    // this is probably an error-case you need to handle
}
if data.Foo == nil {
    fmt.Println("Bar was set")
} else {
    fmt.Println("Foo was set")
}

Не более того

...