Разархивирование JSON в struct, но преобразование значений в требуемые dtypes

#json #rest #http #go

#json #rest #http #Вперед

Вопрос:

Я использую JSON API, для которого я должен разобрать его в struct. Однако API возвращает все значения, четные числа, в виде строк, и мне нужно, чтобы они были в формате чисел. Итак, в настоящее время у меня есть структура, в которой есть поля-члены, которые все являются строками, и после того, как я проанализировал данные, я перебираю записи, чтобы преобразовать значения и добавить их в новую структуру, которая содержит конкретные записи в значениях float или int.

Есть ли какой-либо способ выполнить синтаксический анализ и выполнить преобразование типов за один раз без использования промежуточного структурного представления, из которого можно преобразовать значения в нужные типы данных?

Пример кода

 str := []byte(`
{
    "name": "Jim Burnham",
    "age": "34",
    "dob_day": "22",
    "dob_month": "3",
    "dob_year": "1984"
}
`)
  

Вот пример JSON-объявления ответа от API. Обратите внимание, что возраст, день, месяц и год возвращаются в виде строк, а не целых чисел. Теперь я объявляю структуру с нужными полями с тегами JSON для правильного сопоставления значений:

 type person struct {
    Name   string `json:"name"`
    Age    int `json:"age"`
    DobDay int `json:"dob_day"`
    DobMonth int `json:"dob_month"`
    DobYear int `json:"dob_year"`
}
  

Затем я объявляю экземпляр person struct и использую json пакет, чтобы разархивировать его в экземпляр struct:

 var p person
_ = json.Unmarshal(str, amp;p)
fmt.Println(p)
  

Но когда я распечатываю person, генерируется следующий вывод:

 {Jim Burnham 0 0 0 0}
  

Как вы можете видеть, строка была проанализирована правильно, но другие целочисленные поля остаются в их инициализированном значении Golang по умолчанию. Однако, когда я меняю определение структуры на :

 type person struct {
    Name   string `json:"name"`
    Age    string `json:"age"`
    DobDay string `json:"dob_day"`
    DobMonth string `json:"dob_month"`
    DobYear string `json:"dob_year"`
}
  

Я получаю следующий вывод:

 {Jim Burnham 34 22 3 1984}
  

Это означает, что в настоящее время я должен определить необработанную структуру, которая анализирует информацию в формате строки, но затем определяет другую структуру с желаемыми dtypes и переназначает и преобразует значения отдельно, что также приводит к неопрятному коду. Однако это всего лишь один случай, но в моем случае использования, вероятно, тысячи или даже иногда миллионы таких значений, и это кажется неэффективным даже для скомпилированного языка. Вот почему я прошу решения для такой проблемы.

Комментарии:

1. play.golang.org/p/klHYlMQyb_V

2. … для более сложных случаев вы можете объявить пользовательский тип и реализовать json.Unmarshaler его интерфейс.

3. Это работает так хорошо. Большое вам спасибо. Это аккуратнее, чем json.Number, который предложил кто-то другой.

4. Вы должны опубликовать это как ответ 😉

Ответ №1:

Как хорошо объяснил @mkopriva по этой ссылке: https://play.golang.org/p/klHYlMQyb_V