"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > El misterio de la conversión JSON de IntTo Float64

El misterio de la conversión JSON de IntTo Float64

Publicado el 2024-11-02
Navegar:744

The Mystery Of JSON Conversion Of IntTo Float64

Trabajar con JSON puede parecer simple y claro, tiene alguna estructura, puede cambiarla a JSON: un lenguaje unificado general y volver a su estructura. Sencillo ¿verdad? ?

Bueno, sí, pero eso es hasta que encuentres un comportamiento extraño en las funciones Marshal/Unmarshal.

Problema ?

Todo comenzó cuando intentaba leer la carga útil codificada de un token JWT. A continuación se muestra un ejemplo que demuestra el problema

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)
}

Simplemente ordenando y desordenando la estructura, ¡por lo que se espera que devuelva el mismo valor!

Desafortunadamente, esto no sucedió, el código anterior genera

// Result
id: 0
Ok:false

post_ids: []
Ok:false

Una vez que vi ese resultado, ¿yo? el problema podría estar en las conversiones de tipos, así que fui a comprobar qué tipos tienen estas interfaces

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

Como podemos ver, JSON ha analizado int64 como float64, lo que genera problemas al leer los datos.

En realidad, hay dos formas de solucionar este problema

? Solución 01 (camino difícil)

Utilice afirmaciones de tipo de float64. Tenga en cuenta que []interfaz{} no se puede asignar de inmediato a []float64, por lo que tenemos que iterar cada elemento y convertirlo

        // 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]

? Solución 02 (Manera fácil)

Analizarlo nuevamente en una estructura

    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)

Por supuesto, podrías pensar, ¿por qué deberíamos usar la Solución 01? ¿No es mejor la Solución 02?

Bueno, depende, no siempre deseas crear una estructura para leer un solo atributo de una estructura, por lo que la respuesta correcta es: ¡Depende!

Creo que eso es todo por el artículo de hoy, ¿te gustaría que aprendieras algo nuevo, amigo mío?.

Declaración de liberación Este artículo se reproduce en: https://dev.to/aehelaly/the-mystery-of-json-conversion-of-int64-to-float64-5eof?1 Si hay alguna infracción, comuníquese con [email protected] para borrarlo
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3