Maison >développement back-end >Golang >Le mystère de la conversion JSON de IntTo Float64

Le mystère de la conversion JSON de IntTo Float64

WBOY
WBOYoriginal
2024-09-03 13:20:191139parcourir

The Mystery Of JSON Conversion Of IntTo Float64

Travailler avec JSON peut sembler simple et clair, vous avez une structure, vous pouvez la changer en JSON — Un langage général unifié et revenir à votre structure. Simple, non ? ?

Eh bien, oui, mais c'est jusqu'à ce que vous rencontriez un comportement étrange de la part des fonctions Marshal/Unmarshal.

Problème ?

Tout a commencé lorsque j'essayais de lire la charge utile codée à partir d'un jeton JWT. Vous trouverez ci-dessous un exemple qui illustre le problème

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

Il suffit de marshaler et de démarshaler la structure, donc elle devrait renvoyer la même valeur !

Malheureusement, cela ne s'est pas produit, le code ci-dessus affiche

// Result
id: 0
Ok:false

post_ids: []
Ok:false

Une fois que j'ai vu cette sortie, je ? le problème pourrait venir des conversions de types, alors je suis allé vérifier quels types ont ces interfaces

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

Comme nous pouvons le voir, JSON a analysé int64 comme float64, ce qui entraîne des problèmes lors de la lecture des données.

Il existe en fait 2 façons de résoudre ce problème

? Solution 01 (difficile)

Utilisez les assertions de type de float64, notez que []interface{} ne peut pas être mappée immédiatement sur []float64, nous devons donc itérer chaque élément et le convertir

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

? Solution 02 (facile)

Analysez-le en une structure

    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)

Bien sûr, vous pourriez penser, pourquoi devrions-nous même utiliser la solution 01, la solution 02 n'est-elle pas meilleure ?

Eh bien, cela dépend, vous ne voulez pas toujours créer une structure pour lire un seul attribut d'une structure, donc la bonne réponse est -- Cela dépend !

Je pense que c'est tout pour l'article d'aujourd'hui, j'aimerais que tu aies appris quelque chose de nouveau, mon cher Gopher ?.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn