«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Тайна преобразования JSON IntTo Float64

Тайна преобразования JSON IntTo Float64

Опубликовано 2 ноября 2024 г.
Просматривать:155

The Mystery Of JSON Conversion Of IntTo Float64

Работа с JSON может показаться простой и понятной: у вас есть некоторая структура, вы можете изменить ее на JSON — общий унифицированный язык и вернуться к своей структуре. Просто, правда? ?

Ну да, но это до тех пор, пока вы не столкнетесь со странным поведением функций Marshal/Unmarshal.

Проблема ?

Все началось, когда я пытался прочитать закодированную полезную нагрузку из токена JWT. Ниже приведен пример, демонстрирующий проблему

package main

import (
    "encoding/json"
    "fmt"
)

type User struct {
    ID      int64   `json:"id"`
    PostIDs []int64 `json:"post_ids"`
}

func main() {
    u := User{
        ID:      1,
        PostIDs: []int64{1, 2, 3},
    }

    b, err := json.Marshal(u)
    if err != nil {
        panic(err)
    }

    m := make(map[string]interface{})
    if err = json.Unmarshal(b, &m); err != nil {
        panic(err)
    }

    userID, ok := m["id"].(int64)
    fmt.Printf("id: %d\nOk:%t\n", userID, ok)

    fmt.Println() // spliter

    postIDs, ok := m["id"].([]int64)
    fmt.Printf("post_ids: %v\nOk:%t\n", postIDs, ok)
}

Просто маршалинг и демаршалинг структуры, поэтому ожидается, что она вернет одно и то же значение!

К сожалению, этого не произошло, код выше выводит

// Result
id: 0
Ok:false

post_ids: []
Ok:false

Как только я увидел этот результат, я ? проблема может быть в преобразованиях типов, поэтому я пошел проверить, какие типы имеют эти интерфейсы

    fmt.Printf("id: %T\n", m["id"])
    fmt.Printf("post_ids: %T\n", m["post_ids"])
// Result
id: float64
post_ids: []interface {}

Итак, как мы видим, JSON анализирует int64 как float64, что приводит к проблемам при чтении данных.

На самом деле существует два способа решить эту проблему

? Решение 01 (сложный способ)

Используйте утверждения типа float64. Обратите внимание, что []interface{} нельзя сразу сопоставить с []float64, поэтому нам приходится перебирать каждый элемент и конвертировать его

        // Parse UserID
    userID, _ := m["id"].(float64)
    fmt.Printf("id: %f\n", userID)

    fmt.Println() // spliter

    // Parse PostIDs
    postIDsArr, _ := m["post_ids"].([]interface{})
    postIDs := make([]int64, len(postIDsArr))
    for i, v := range postIDsArr {
        id, _ := v.(float64) // NOTICE: direct conversion to int64 won't work here!
        postIDs[i] = int64(id)
    }

    fmt.Printf("post_ids: %v\n", postIDs)
// Result
id: 1.000000

post_ids: [1 2 3]

? Решение 02 (Простой способ)

Разберите его обратно в структуру

    b, err = json.Marshal(m) // m = map[string]interface{}
    if err != nil {
        panic(err)
    }

    var u2 User
    if err := json.Unmarshal(b, &u2); err != nil {
        panic(err)
    }

    fmt.Println(u2.ID)
    fmt.Println(u2.PostIDs)

Конечно, вы можете подумать: зачем нам вообще использовать Решение 01, разве Решение 02 не лучше?

Ну, это зависит от того, вы не всегда хотите создавать структуру для чтения одного атрибута из структуры, поэтому правильный ответ: — Это зависит!

Думаю, на сегодня это все, желаю тебе узнать что-то новое, мой друг-суслик?.

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/aehelaly/the-mystery-of-json-conversion-of-int64-to-float64-5eof?1 Если есть какие-либо нарушения, пожалуйста, свяжитесь с [email protected] удалить его
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3