"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > O mistério da conversão JSON de IntTo Float64

O mistério da conversão JSON de IntTo Float64

Publicado em 2024-11-02
Navegar:883

The Mystery Of JSON Conversion Of IntTo Float64

Trabalhar com JSON pode parecer simples e claro, você tem alguma estrutura, pode alterá-la para JSON - uma linguagem geral unificada e de volta à sua estrutura. Simples, certo? ?

Bem, sim, mas isso é até você encontrar algum comportamento estranho das funções Marshal / Unmarshal.

Problema ?

Tudo começou quando eu estava tentando ler o payload codificado de um token JWT, abaixo está um exemplo que demonstra o 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)
}

Apenas empacotando e desempacotando a estrutura, então espera-se que retorne o mesmo valor!

Infelizmente, isso não aconteceu, o código acima gera

// Result
id: 0
Ok:false

post_ids: []
Ok:false

Assim que vi esse resultado, eu ? o problema pode ser com conversões de tipo, então fui verificar quais tipos essas interfaces possuem

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

Então, como podemos ver, JSON analisou int64 como float64, o que leva a problemas na leitura dos dados.

Na verdade, existem duas maneiras de corrigir esse problema

? Solução 01 (maneira difícil)

Use asserções de tipo float64. Observe que a []interface{} não pode ser mapeada imediatamente para []float64, então temos que iterar cada elemento e convertê-lo

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

? Solução 02 (maneira fácil)

Analisar de volta para uma estrutura

    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)

Claro, você pode pensar, por que deveríamos usar a Solução 01, a Solução 02 não é melhor?

Bem, depende, você nem sempre deseja criar uma estrutura para ler um único atributo de uma estrutura, então a resposta correta é - Depende!

Acho que é tudo para o artigo de hoje, gostaria que você aprendesse algo novo, meu colega esquilo?.

Declaração de lançamento Este artigo foi reproduzido em: https://dev.to/aehelaly/the-mystery-of-json-conversion-of-int64-to-float64-5eof?1 Se houver alguma violação, entre em contato com [email protected] para excluí-lo
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3