"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > سر تحويل JSON إلى IntTo Float64

سر تحويل JSON إلى IntTo Float64

تم النشر بتاريخ 2024-11-02
تصفح:991

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