Я действительно не уверен, в чем проблема.Стандарт encoding/json
не требует, чтобы структура соответствовала всем полям в данных JSON.Это довольно легко сделать с помощью одного простого типа:
type Payload struct {
ID int `json:"id"`
Title string `json:"title"`
Message string `json:"message"`
}
type Response struct {
Status string `json:"status"`
ID string `json:"request_id"`
TraceID string `json:"trace_id"`
Payload Payload `json:"payload"`
}
Затем просто разархивируйте ответ в Response
struct:
var resp Response
if err := json.Unmarshal(body, &resp); err != nil {
return err
}
Затем вы можете просто проверить Status
поле, и решить, что делать дальше.Например:
if resp.Status == "error" {
return fmt.Errorf("invalid response: %s - %s", resp.TraceID, resp.Payload.Message)
}
// handle resp.Payload.ID and resp.Payload.Title fields
return nil
Вы можете переместить эти проверки для поля состояния в функции получателя на объекте ответа, в зависимости от сложности и ваших конкретных потребностей.
Возможно, стоит использовать поля указателядля тех полей, которые не заданы в обычном ответе, и пометьте их параметром omitempty
:
type Payload struct {
ID int `json:"id"`
Title string `json:"title"`
Message *string `json:"message,omitempty"`
}
type Response struct {
Status string `json:"status"`
ID string `json:"request_id"`
TraceID *string `json:"trace_id,omitempty"`
Payload Payload `json:"payload"`
}
С такими типами больше не нужно полагаться на жестко закодированные строковые константы для проверкиза ошибки.Вместо этого вы можете легко реализовать более общую проверку, например, так:
func (r Response) IsError() bool {
return (r.TraceID == nil) // will be set in case of an error response
}
Обновление
Как вы указали в комментариях, тело ответа на самом деле значительно больше, чем 2поля в примере.Конечно, копирование структурных определений или написание функций отображения для сопоставления Payload
с уже имеющимся типом немного бессмысленно.
Ответ здесь такой: состав.
type Payload struct {
AppStruct // embedded the AppStruct type
Message *string `json:"message"`
}
Тип Response
остается без изменений.Если ответ успешен, вы можете получить AppStruct
непосредственно из ответа следующим образом:
appStruct := resp.Payload.AppStruct
Это работает, потому что тип встроен.Обратите внимание, что там нет тегов json
.Встроенная структура, по крайней мере, в том, что касается unmarshalling, является частью структуры Payload
.Следовательно, все экспортируемые поля этого типа будут распакованы непосредственно в структуру.