1. encoding/json স্ট্যান্ডার্ড লাইব্রেরির ওভারভিউ

Go ভাষা সরবরাহ করে একটি শক্তিশালী encoding/json লাইব্রেরি যা JSON ডেটা ফরম্যাট নিয়ে কাজ করতে। এই লাইব্রেরি দিয়ে, আপনি সহজে গো ডেটা টাইপগুলি কে JSON ফরম্যাটে রূপান্তর করতে পারবেন (সিরিয়ালাইজেশন) অথবা JSON ডেটা কে গো ডেটা টাইপগুলির মধ্যে রূপান্তর করতে পারবেন (ডিসিরিয়ালাইজেশন)। এই লাইব্রেরি বিশেষত এনকোডিং, ডিকোডিং, স্ট্রিমিং আইও, এবং কাস্টম JSON পার্সিং লজিকের সাপোর্ট সরবরাহ করে।

এই লাইব্রেরিতে সবচেয়ে গুরুত্বপূর্ণ ডেটা টাইপ এবং ফাংশন গুলি হল:

  • Marshal এবং MarshalIndent: গো ডেটা টাইপগুলি কে JSON স্ট্রিংগে সিরিয়ালাইজ করতে ব্যবহৃত।
  • Unmarshal: JSON স্ট্রিংগগুলি কে গো ডেটা টাইপগুলির মধ্যে ডিসিরিয়ালাইজ করতে ব্যবহৃত।
  • Encoder এবং Decoder: স্ট্রিমিং আইও এর জন্য JSON ডেটা এবং সাধারণ বিদেশী মূল্য সাপোর্ট করার জন্য ব্যবহৃত।
  • Valid: দেওয়া স্ট্রিংগটি যথাযোগ্য JSON ফরম্যাট কি না তা চেক করার জন্য ব্যবহৃত।

আমরা প্রতিষ্ঠান করে আসব আগামী অধ্যায়গুলিতে এই ফাংশনগুলি এবং টাইপগুলি এর ব্যবহার শিখব।

2. গো ডেটা স্ট্রাকচার কে JSON এ সিরিয়ালাইজ করা

2.1 json.Marshal ব্যবহার

json.Marshal হল একটি ফাংশন যা গো ডেটা টাইপগুলি কে JSON স্ট্রিংগে সিরিয়ালাইজ করে। এটি গো ভাষার ডেটা টাইপ নিয়ে ইনপুট হিসাবে নিয়ে JSON ফরম্যাটে রূপান্তর করে এবং একইসাথে সম্ভাব্য ভুল দিয়ে বাইট স্লাইস রিটার্ন করে।

এখানে একটি সাধারণ উদাহরণ দেখানো হল যেখানে দেখানো হয় যেভাবে গো স্ট্রাক্ট কে কীভাবে JSON স্ট্রিংগে রূপান্তর করা যায়:

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    person := Person{"Alice", 30}
    jsonData, err := json.Marshal(person)
    if err != nil {
        log.Fatalf("JSON marshaling failed: %s", err)
    }
    fmt.Println(string(jsonData)) // আউটপুট: {"name":"Alice","age":30}
}

স্ট্রাক্টের পাশাপাশি json.Marshal ফাংশন ব্যবহার করে ম্যাপ এবং স্লাইস প্রকারের অন্যান্য ডেটা টাইপ এর সিরিয়ালাইজ করা সম্ভব। নিচে map[string]interface{} এবং slice ব্যবহার করে উদাহরণ দেওয়া হল:

// ম্যাপকে JSON তে রূপান্তর করুন
myMap := map[string]interface{}{
    "name": "Bob",
    "age":  25,
}
jsonData, err := json.Marshal(myMap)
// ... ভুল হ্যান্ডলিং এবং আউটপুট অমিট ...

// স্লাইসকে JSON তে রূপান্তর করুন
mySlice := []string{"Apple", "Banana", "Cherry"}
jsonData, err := json.Marshal(mySlice)
// ... ভুল হ্যান্ডলিং এবং আউটপুট অমিট ...

2.2 স্ট্রাকচার ট্যাগ

গোতে, স্ট্রাকচার ট্যাগ ব্যবহার করা হয় স্ট্রাকচার ফিল্ডের জন্য মেটাডেটা সরবরাহ করার জন্য, JSON সিরিয়ালাইজেশনের আচরণকে নিয়ন্ত্রণ করা। ইগুলির সবচেয়ে সাধারণ ব্যবহারের ক্ষেত্র ফিল্ডের নাম পরিবর্তন, কিছু ফিল্ডগুলির উপেক্ষণ এবং শর্তবিদ্ধ সিরিয়ালাইজেশন।

উদাহরণস্বরূপ, আপনি ট্যাগ json:"<name>" ব্যবহার করে JSON ফিল্ডের নাম নির্ধারণ করতে পারেন:

type Animal struct {
    SpeciesName string `json:"species"`
    Description string `json:"desc,omitempty"`
    Tag         string `json:"-"` // এখানে "-" ট্যাগ যোগ করা হয়েছে ইন্ডিকেট করার জন্য যে এই ফিল্ডটি সিরিয়ালাইজ হবে না।
}

উপরের উদাহরণে, Tag ফিল্ডের সামনে json:"-" ট্যাগ ব্যবহার করা হয়েছে, যা সূচিত করে json.Marshal কে এই ফিল্ডটি উপেক্ষা করতে। Description ফিল্ডের জন্য omitempty অপশন ব্যবহার করা হয়েছে, যা মানে যদি ফিল্ডটি খালি (শূন্য মান, উদাহরণস্বরূপ খালি স্ট্রিং) হয়, তবে সে সিরিয়ালাইজড JSON এ সংক্ষেপণ করা হবে না।

একটি সম্পূর্ণ উদাহরণস্বরূপ স্ট্রাকচার ট্যাগ ব্যবহারের জন্য দেওয়া হল:

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

type Animal struct {
    SpeciesName string `json:"species"`
    Description string `json:"desc,omitempty"`
    Tag         string `json:"-"`
}

func main() {
    animal := Animal{
        SpeciesName: "African Elephant",
        Description: "A large mammal with a trunk and tusks.",
        Tag:         "endangered", // এই ফিল্ডটি সিরিয়ালাইজ হবে না আদি পাশাপাশি
    }
    jsonData, err := json.Marshal(animal)
    if err != nil {
        log.Fatalf("JSON marshaling failed: %s", err)
    }
    fmt.Println(string(jsonData)) // আউটপুট: {"species":"African Elephant","desc":"A large mammal with a trunk and tusks."}
}

এই ভাবে, আপনি ডাটা স্ট্রাকচার প্রকারটি নিয়ন্ত্রণ করতে পারেন এবং JSON প্রতিনিধিত্ব নিশ্চিত করতে পারেন, বিভিন্ন সিরিয়ালাইজেশনের প্রয়োজনীয়তা সম্ভবতা তৈরি করতে।

3. JSON এর ভিতে গো ডেটা স্ট্রাকচারে ডিসিরিয়ালাইজ করা

3.1 json.Unmarshal ব্যবহার

json.Unmarshal ফাংশন আমাদেরকে JSON স্ট্রিংগগুলি কো Go ডেটা স্ট্রাকচারে পার্স করতে অনুমতি দেয়, যেমন structs, maps, ইত্যাদি। json.Unmarshal ব্যবহার করতে, আমাদের প্রথমে সাজানো হলে Go ডেটা স্ট্রাকচার, যা JSON ডেট

4.2 JSON Arrays

JSON এ, অ্যারে গুলো একটি সাধারণ ডাটা স্ট্রাকচার। Go তে, এগুলোর জন্য স্লাইসের সাথে সম্পর্কিত।

নিম্নলিখিত JSON অ্যারেটি বিবেচনা করুন:

[
    {"name": "ডেভ", "age": 34},
    {"name": "ইভ", "age": 28}
]

Go তে, আমরা নিম্নোক্ত স্ট্রাক্চার এবং স্লাইসটি এর অনুরূপ সংজ্ঞায়িত করি:

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    jsonData := `[
        {"name": "ডেভ", "age": 34},
        {"name": "ইভ", "age": 28}
    ]`

    var people []Person
    json.Unmarshal([]byte(jsonData), &people)
    
    for _, person := range people {
        fmt.Printf("%+v\n", person)
    }
}

এই ভাবে, আমরা প্রতিটি উপাদানকে JSON অ্যারে থেকে গো স্লাইস অব গো স্ট্রাক্চারে পুনরায় ডিসিরিয়ালাইজ করতে পারি অনুরূপ প্রসেসিং এবং অ্যাক্সেসের জন্য।

5 ত্রুটি অভ্যন্তরীণণ

JSON ডাটা সঙ্গে কাজ করার সময়, সিরিয়ালাইজেশন (স্ট্রাকচারযুক্ত ডাটা কে জেএসওএন ফর্ম্যাটে প্রেরণ) বা ডিসিরিয়ালাইজেশন (জেএসওএন কে পুনরায় স্ট্রাকচারযুক্ত ডাটা বন্ধন করা) এরর সংবন্ধে জনপ্রিয় ত্রুটিগুলি এবং তাদের কীভাবে হ্যান্ডেল করা হয়ো।

5.1 সিরিয়ালাইজেশন এরর হ্যান্ডেলিং

সিরিয়ালাইজেশন এরর গুলি সাধারণভাবে একটি স্ট্রাকচার বা অন্যান্য ডাটা টাইপ কে জেএসওএন স্ট্রিং এ রূপান্তর করার প্রক্রিয়ায় দোষো হয়। উদাহরণস্বরূপ, যদি একটি স্ট্রাকচারে অবৈধ ফিল্ডস সম্পন্ন করা হয় (যেমন, জেএসওএন এ প্রতিনিধিত্ব করা যায় না যেমন একটি চ্যানেল ধরন বা কার্য্যাদি), json.Marshal একটি এরর রিটার্ন করবে।

import (
    "encoding/json"
    "fmt"
    "log"
)

type User struct {
    Name string
    Age  int
    // এখানে যো কি একটি ফিল্ড থাকবে তা ইন্টেনশনালি কমেেন্ট করা হয়েছে
    // ডেটা chan struct{} // চ্যানেল জেএসওএন এ নিউম্নিক অবস্থা প্রসতুত করা যায় / না
}

func main() {
    u := User{
        Name: "অ্যালিস",
        Age:  30,
        // ডেটা: make(chan struct{}),
    }

    bytes, err := json.Marshal(u)
    if err != nil {
        log.Fatalf("JSON সিরিয়ালাইজেশন ফেইল: %v", err)
    }
    
    fmt.Println(string(bytes))
}

উপরের উদাহরণে, আমরা ইনটেনশনালি ডাটা ফিল্ডটি কমোন্ট করেছি। যদি ইহা কমেন্ট না করা হত, সিরিয়ালাইজেশন ব্যারগু ত্রুটি হয়তো এবং কোডটি এরর লগ কদরবে এবং প্রযন্তালে ত্রুটিটা হ্যান্ডেল করার উপায়গুলি (যেমন ত্রুটিগুলি লগ করা, ডিফল্ট ডেটা ফেরত দেওয়া, ইত্যাদি) ব্যাবহার করা।

5.2 ডিসিরিয়ালাইজেশন এরর হ্যান্ডেলিং

ডিসিয়ারলাইজেশন এরর গুলি সাধারণভাবে সম্প্রদায় ডাটা স্ট্রিং কে পুনরু-অ্যাপ গো স্ট্রাকচার বা অন্যান্য ডাটা টাইপ এ রূপান্তর করার প্রসেসিং করার ফসতে। উদাহরণস্বরূপ, যদি জেএসওএন স্ট্রিং ফর্ম্যাট অযমিত বা লক্ষ্ময়াহ্য কোনো টাইপ প্রকল্প্টি সাথে সাথে, json.Unmarshal একটি এরর রিটার্ন করবে।

import (
    "encoding/json"
    "fmt"
    "log"
)

func main() {
    var data = []byte(`{"name":"অ্যালিস","age":"অজানা"}`) // "যুগ" একটি ইন্টিজার হওয়া উচিত, কিন্তু ইচ্ছিত হয়েই এখানে একটি স্ট্রিং দেওয়া হয়েছে
    var u User

    err := json.Unmarshal(data, &u)
    if err != nil {
        log.Fatalf("JSON ডেসিরিয়ালাইজেশন ফেইলড: %v", err)
    }
    
    fmt.Printf("%+v\n", u)
}

এই কোড উদাহরণে, আমরা ইচ্ছাকৃত ভাবে যুগ ফিল্ডের জন্য ভুল ডেটা টাইপ পরিবর্তন করতে তা কন্টেইন করা হয়েছে (স্ট্রিং বিকেআপ অপেক্ষা হচ্ছে ইন্টিজার), যোগ করা চোলে, json.Unmarshal একটি এরর থ্রো করবে। সুতরাং, আমরা এই অবস্থানকে সঠিকভাবে হ্যান্ডেল করতে হবে। সাধারণ অনুশাসনে, ত্রুটি বার্তা লগ করা এবং, আপাগু পর্যাই, সম্ভাব্যতঃ খালি অবজেক্ট, ডিফল্ট ভ্যালু, অথবা ত্রুটি বার্তা রিটার্ন করা, স্বাভাবিক অভ্যন্তরীণণ পদ্ধতি।

6 উন্নত বৈশিষ্ট্য এবং কার্যকরীকরণের মান্যশাল

6.1 কাস্টম মার্শাল এবং আনমার্শাল

গোতে, ডিফল্টভাবে, encoding/json প্যাকেজ JSON সারিয়ালাইজ এবং ডিসারিয়ালাইজ প্রক্রিয়া রিফ্লেকশন দ্বারা করে। তাছাত, আমরা json.Marshaler এবং json.Unmarshaler ইন্টারফেস ইমপ্লিমেন্ট করে এই প্রক্রিয়া সাধন করা সম্ভব।

import (
    "encoding/json"
    "fmt"
)

type Color struct {
    Red   uint8
    Green uint8
    Blue  uint8
}

func (c Color) MarshalJSON() ([]byte, error) {
    hex := fmt.Sprintf("\"#%02x%02x%02x\"", c.Red, c.Green, c.Blue)
    return []byte(hex), nil
}

func (c *Color) UnmarshalJSON(data []byte) error {
    _, err := fmt.Sscanf(string(data), "\"#%02x%02x%02x\"", &c.Red, &c.Green, &c.Blue)
    return err
}

func main() {
    c := Color{Red: 255, Green: 99, Blue: 71}
    
    jsonColor, _ := json.Marshal(c)
    fmt.Println(string(jsonColor))

    var newColor Color
    json.Unmarshal(jsonColor, &newColor)
    fmt.Println(newColor)
}

এখানে, আমরা Color ধরন সংজ্ঞায়িত করেছি এবং MarshalJSON এবং UnmarshalJSON মেথড ইমপ্লিমেন্ট করেছি যাতে আরজিবি রঙগুলি হেক্সাডেসিমাল স্ট্রিংসে পরিণত এবং পুনরায় আরজিবি রং হিসাবে ফিরিয়ে আসা সম্ভব।

6.2 এনকোডার এবং ডিকোডার

বড় JSON ডেটা সম্পর্কিত কাজ করার সময়, সরাসরি json.Marshal এবং json.Unmarshal ব্যবহার করা অতিরিক্ত মেমরি ব্যবহার বা অদক্ষ ইনপুট/আউটপুট অপারেশনের কারণে প্রচুর সময় নেওয়া অথবা দুর্বল হতে পারে। তাই, গোতে encoding/json প্যাকেজ এনকোডার এবং ডিকোডার ধরণ উপলব্ধ করা হয়েছে, যেগুলি JSON ডেটা একটি স্ট্রিমিং ফ্যাশনে প্রসেস করতে পারে।

6.2.1 json.Encoder ব্যবহার করা

json.Encoder সরাসরি যে কোনও অবজেক্টে JSON ডেটা লিখতে পারে যা io.Writer ইন্টারফেস ইমপ্লিমেন্ট করে, অর্থাৎ, আপনি প্রকারিত JSON ডেটা নির্ধারণ করে একটি ফাইল, নেটওয়ার্ক সংযোগ ইত্যাদি ধরণের অবজেক্টে সরাসরি এনকোড করতে পারেন।

import (
    "encoding/json"
    "os"
)

func main() {
    users := []User{
        {Name: "Alice", Age: 30},
        {Name: "Bob", Age: 25},
    }
    
    file, _ := os.Create("users.json")
    defer file.Close()
    
    encoder := json.NewEncoder(file)
    if err := encoder.Encode(users); err != nil {
        log.Fatalf("Encoding error: %v", err)
    }
}

6.2.2 json.Decoder ব্যবহার করা

json.Decoder সরাসরি পড়তে পারে যে কোনও অবজেক্ট যা io.Reader ইন্টারফেস ইমপ্লিমেন্ট করে, JSON অবজেক্ট এবং অ্যারে খুঁজে পাওয়া এবং পার্স করা।

import (
    "encoding/json"
    "os"
)

func main() {
    file, _ := os.Open("users.json")
    defer file.Close()
    
    var users []User
    decoder := json.NewDecoder(file)
    if err := decoder.Decode(&users); err != nil {
        log.Fatalf("Decoding error: %v", err)
    }
    
    for _, u := range users {
        fmt.Printf("%+v\n", u)
    }
}

এনকোডার এবং ডিকোডার দ্বারা ডেটা প্রসেস করে, আপনি পাড়ার সময়ে JSON প্রসেসিং করতে পারেন, মেমরি ব্যবহার কমিয়ে, প্রসেসিং দক্ষতা বাড়ানো যায়, যা নেটওয়ার্ক ট্রান্সফার বা বড় ফাইল সম্পর্কে বিশেষ ভাবে উপযোগী।