@SignOfChaos

Структура с полем, содержащим JSON-строку. Как из такой структуры получить правильный JSON?

Добрый день!

есть структура
type DetailedReportRow struct {
	Id           int64      `json:"id"`
	Dt           *time.Time `json:"dt"`
	Phone        string     `json:"phone"`
	TicketSums   string	  `json:"tickets" sql:"type:json"`
	PaymentSum   float32    `json:"payment_sum"`
	PaySystemId  float32    `json:"pay_system_id"`
	PayStateName string     `json:"pay_state_name"`
	BusNo		string	  `json:"bus_no"`
}


есть запрос к БД PostgreSQL, результат которого заполняет массив экземпляров указанной структуры
...
var result []models.DetailedReportRow
...
slq := fmt.Sprintf(`
		select 
			p.id,
			p.success_dt as dt,
			p.phone,
			p.payment_sum,
			p.pay_system_id,
			ps.name as pay_state_name,
			bb.state_number as bus_no,
			p.json_data_r::json->>'s' as ticket_sums -- элемент s содержит массив простых объектов вида [{"p": 90}, {"p": 90}]
		FROM 
			pay_payment p
			LEFT JOIN pay_state ps on	ps.id = p.pay_state_id
			LEFT JOIN bus_bus bb on (bb.qr = p.json_data_r::json->>'q')
		...
`)

	controllers.DB.Raw(slq).Scan(&result)
	return result

поле ticket_sums, понятное дело, возвращается как строка.
далее полученный результат позвращается клиенту из контроллера Revel:
func (c ManagerAuthApiCtl) BusDetailedReport() revel.Result {
	...
	stat := repository.Bus().DetailedReport(date, system, fleet)
	return c.RenderJSON(JsonResponse{
		Success: true,
		Data:    map[string]interface{}{"stat": stat},
	})
}


клиенту прилетает json вот такого вида:
{
  "success": true,
  "data": {
    "stat": [
      {
        "id": 185247,
        "dt": "2018-10-18T18:36:07Z",
        "phone": "0000000000",
        "tickets": "[{\"p\": 90}, {\"p\": 90}]",
        "payment_sum": 180,
        "pay_system_id": 1,
        "pay_state_name": "Успешно оплачен",
        "bus_no": "157 АТ 01"
      },
      ...
    ]
  }
}

нужно, чтобы
"tickets": "[{\"p\": 90}, {\"p\": 90}]"
было:
"tickets": [{"p": 90}, {"p": 90}]
т.е. как массив объектов, а не строка с escaped quotes

поиски по интернетам привели к тому, что поле структуры содержащее json, должно объявляться вот так:
type DetailedReportRaw struct {
	...
	TicketSums	 json.RawMessage		`json:"tickets"`
	...
}

, но при этом в выдаваемом json'е поле tickets равно nil

Подскажите, кто сталкивался, как получить желаемый результат?
Спасибо!
  • Вопрос задан
  • 210 просмотров
Пригласить эксперта
Ответы на вопрос 3
Вам просто нужно сделать поле tickets типом string и анмаршалить прямо из него, приведя к типу []byte.

result := map[string]int{}
json.Unmarshal([]byte(someStruct.tickets), &result)
Ответ написан
Комментировать
@Abcdefgk
Надо на клиенте выкинуть эти слеши из строки да и всё - str.replace(/\\/g, '');
"tickets": "[{"p": 90}, {"p": 90}]",
Ответ написан
Комментировать
@bat
поиски по интернетам привели к json.RawMessage

направление правильное
но при этом в выдаваемом json'е поле tickets равно nil

возможно, что controllers.DB.Raw(slq).Scan(&result) не умееть работать с этим типом
попробуйте, что будет если объявить поле как
TicketSums []byte
будут ли в нем данные, если да, то можно копать дальше

анмаршалить строчку, как предложили выше, можно, если надо быстро зафиксить. Как решение - костыльно, ненужный оверхед на декодирование/кодирование уже готового json.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы