Как обрабатывать переменную структуры nil в типе структуры - PullRequest
0 голосов
/ 03 мая 2019

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

type A struct {
  Id string `json:"id"`
  Version string `json:"version"`
  Actors []actor `json:"actors`
  Payload struct {
     Name string `json:"name"`
     Number string `json:"number"`
  }
}
type payload struct {
    Name string `json:"name"`
    Number string `json:"number"`
}
type actor struct {
    Id   string `json:"id"`
    Type string `json:"type"`
    Role string `json:"role"`
}

Актеры или полезные данные могут быть пустыми. JSON может быть

{
  "id": "78a07cea-be2b-499c-b82b-e4f510260484",
  "version": "1.0.0",
  "actors": [
    {
      "id": "1234567",
      "type": "XXX",
      "role": "111"
    },
    {
      "id": "7654321",
      "type": "YYY",
      "role": "222"
    }
  ],
  "payload": ""
}

или

{
  "id": "78a07cea-be2b-499c-b82b-e4f510260484",
  "version": "1.0.0",
  "actors": [],
  "payload": {
       "name": "XXXX",
       "number": "1234567"
   }
}

Если я следую структуре struct A и пытаюсь маршалировать json с пустой полезной нагрузкой, я должен инициализировать, как показано ниже

a := A{
  Id: "78a07cea-be2b-499c-b82b-e4f510260484",
  Version: "1.0.0",
  Actors: []actor{
    actor{
      Id: "1234567",
      Type: "XXX",
      Role: "111",
    },
    actor{
      Id: "7654321",
      Type: "YYY",
      Role: "222",
    },
  },
  Payload: payload{},
}

В результате ниже json с одной пустой структурой полезной нагрузки

{
  "id": "78a07cea-be2b-499c-b82b-e4f510260484",
  "version": "1.0.0",
  "actors": [
    {
      "id": "1234567",
      "type": "XXX",
      "role": "111"
    },
    {
      "id": "7654321",
      "type": "YYY",
      "role": "222"
    }
  ],
  "payload": {
     "name":"",
     "number":""
   }
}

Есть ли способ, которым я могу генерировать

"Полезная нагрузка": ""

вместо пустой структуры полезной нагрузки? Или есть какой-либо другой дизайн структуры для этого вида формата JSON? Кстати, я не могу передать ноль в структуру полезной нагрузки.

Ответы [ 2 ]

3 голосов
/ 03 мая 2019

Интерфейс json.Marshaler может быть реализован для настройки кодировки JSON, а интерфейс json.Unmarshaler для декодирования (оставлен как упражнение для читателя):

package main

import (
    "encoding/json"
    "fmt"
)

type A struct {
    Payload payload
}

type payload struct {
    Name   string `json:"name"`
    Number string `json:"number"`
}

func (p payload) MarshalJSON() ([]byte, error) {
    if p.Name == "" && p.Number == "" {
        return []byte(`""`), nil
    }

    type _payload payload // prevent recursion
    return json.Marshal(_payload(p))
}

func main() {
    var a A
    b, _ := json.MarshalIndent(a, "", "  ")
    fmt.Println(string(b))

    a.Payload.Name = "foo"
    b, _ = json.MarshalIndent(a, "", "  ")
    fmt.Println(string(b))
}

// Output:
// {
//   "Payload": ""
// }
// {
//   "Payload": {
//     "name": "foo",
//     "number": ""
//   }
// }

Попробуйте на игровой площадке: https://play.golang.org/p/9jhSWnKTnTf

Специальный тип _payload необходим для предотвращения рекурсии.Если бы вы написали return json.Marshal(p), пакет json снова вызвал бы MarshalJSON, потому что p имеет тип payload, а payload реализует json.Marshaler.

Тип _payload имеет то же самоебазовый тип как payload, но не реализует json.Marshaler (см. определения типов ), поэтому он кодируется с использованием стандартных правил пакета json;он выдает точно такой же вывод, что и кодирование значения типа payload, если бы payload не реализовал json.Marshaler.

1 голос
/ 03 мая 2019

Проверьте, помогает ли использование omitempty с тегом структуры json. Я думаю, что это приведет к "payload": {} вместо "payload": ""

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