Encoding dan Decoding

Go menyediakan berbagai package untuk encoding dan decoding data dalam format yang berbeda seperti JSON, XML, dan binary.

Contoh Masalah

Bagaimana cara:

  1. Mengubah struct ke JSON dan sebaliknya
  2. Bekerja dengan XML
  3. Menggunakan encoding binary
  4. Custom marshaling

Penyelesaian

package main

import (
    "encoding/json"
    "encoding/xml"
    "encoding/gob"
    "fmt"
    "os"
    "time"
)

// 1. Basic struct untuk JSON
type Person struct {
    Name      string    `json:"name" xml:"name"`
    Age       int       `json:"age" xml:"age"`
    Address   string    `json:"address,omitempty" xml:"address,omitempty"`
    BirthDate time.Time `json:"birth_date" xml:"birth_date"`
    Private   string    `json:"-" xml:"-"` // Akan dilewati
}

// 2. Nested struct untuk XML
type Company struct {
    XMLName xml.Name `xml:"company"`
    Name    string   `xml:"name,attr"`
    Address string   `xml:"address"`
    People  []Person `xml:"people>person"`
}

// 3. Custom marshaling
type Duration struct {
    time.Duration
}

func (d Duration) MarshalJSON() ([]byte, error) {
    return json.Marshal(d.String())
}

func (d *Duration) UnmarshalJSON(b []byte) error {
    var v interface{}
    if err := json.Unmarshal(b, &v); err != nil {
        return err
    }
    
    switch value := v.(type) {
    case float64:
        d.Duration = time.Duration(value)
    case string:
        var err error
        d.Duration, err = time.ParseDuration(value)
        if err != nil {
            return err
        }
    default:
        return fmt.Errorf("invalid duration")
    }
    
    return nil
}

// 4. Struct untuk binary encoding
type Message struct {
    ID      int
    Content string
    Time    time.Time
}

func main() {
    // Contoh 1: JSON Encoding/Decoding
    fmt.Println("JSON Example:")
    
    person := Person{
        Name:      "John Doe",
        Age:       30,
        Address:   "Jakarta",
        BirthDate: time.Date(1993, 1, 1, 0, 0, 0, 0, time.UTC),
        Private:   "rahasia",
    }

    // Marshal ke JSON
    jsonData, err := json.MarshalIndent(person, "", "    ")
    if err != nil {
        fmt.Printf("Error marshaling JSON: %v\n", err)
        return
    }
    fmt.Printf("JSON:\n%s\n", string(jsonData))

    // Unmarshal dari JSON
    var decodedPerson Person
    err = json.Unmarshal(jsonData, &decodedPerson)
    if err != nil {
        fmt.Printf("Error unmarshaling JSON: %v\n", err)
        return
    }
    fmt.Printf("Decoded: %+v\n", decodedPerson)

    // Contoh 2: XML Encoding/Decoding
    fmt.Printf("\nXML Example:\n")
    
    company := Company{
        Name:    "Tech Corp",
        Address: "Silicon Valley",
        People: []Person{
            person,
            {
                Name:      "Jane Smith",
                Age:       28,
                BirthDate: time.Date(1995, 1, 1, 0, 0, 0, 0, time.UTC),
            },
        },
    }

    // Marshal ke XML
    xmlData, err := xml.MarshalIndent(company, "", "    ")
    if err != nil {
        fmt.Printf("Error marshaling XML: %v\n", err)
        return
    }
    fmt.Printf("XML:\n%s\n", string(xmlData))

    // Unmarshal dari XML
    var decodedCompany Company
    err = xml.Unmarshal(xmlData, &decodedCompany)
    if err != nil {
        fmt.Printf("Error unmarshaling XML: %v\n", err)
        return
    }
    fmt.Printf("Decoded company name: %s\n", decodedCompany.Name)

    // Contoh 3: Custom Marshaling
    fmt.Printf("\nCustom Marshaling Example:\n")
    
    type Task struct {
        Name     string   `json:"name"`
        Duration Duration `json:"duration"`
    }

    task := Task{
        Name:     "Long Task",
        Duration: Duration{time.Hour * 2},
    }

    // Marshal ke JSON
    taskJSON, err := json.MarshalIndent(task, "", "    ")
    if err != nil {
        fmt.Printf("Error marshaling task: %v\n", err)
        return
    }
    fmt.Printf("Task JSON:\n%s\n", string(taskJSON))

    // Unmarshal dari JSON
    var decodedTask Task
    err = json.Unmarshal(taskJSON, &decodedTask)
    if err != nil {
        fmt.Printf("Error unmarshaling task: %v\n", err)
        return
    }
    fmt.Printf("Decoded task duration: %v\n", decodedTask.Duration.Duration)

    // Contoh 4: Binary Encoding (gob)
    fmt.Printf("\nBinary Encoding Example:\n")
    
    msg := Message{
        ID:      1,
        Content: "Hello, World!",
        Time:    time.Now(),
    }

    // Encode ke file
    file, err := os.Create("message.gob")
    if err != nil {
        fmt.Printf("Error creating file: %v\n", err)
        return
    }
    encoder := gob.NewEncoder(file)
    err = encoder.Encode(msg)
    file.Close()
    if err != nil {
        fmt.Printf("Error encoding: %v\n", err)
        return
    }

    // Decode dari file
    file, err = os.Open("message.gob")
    if err != nil {
        fmt.Printf("Error opening file: %v\n", err)
        return
    }
    var decodedMsg Message
    decoder := gob.NewDecoder(file)
    err = decoder.Decode(&decodedMsg)
    file.Close()
    if err != nil {
        fmt.Printf("Error decoding: %v\n", err)
        return
    }
    fmt.Printf("Decoded message: %+v\n", decodedMsg)

    // Cleanup
    os.Remove("message.gob")
}

Penjelasan Kode

  1. JSON

    • Marshal/Unmarshal
    • Struct tags
    • Pretty printing
  2. XML

    • XML tags
    • Nested structures
    • Attributes
  3. Binary

    • Gob encoding
    • File I/O
    • Custom types

Output

JSON Example:
JSON:
{
    "name": "John Doe",
    "age": 30,
    "address": "Jakarta",
    "birth_date": "1993-01-01T00:00:00Z"
}
Decoded: {Name:John Doe Age:30 Address:Jakarta BirthDate:1993-01-01 00:00:00 +0000 UTC Private:}

XML Example:
XML:
<company name="Tech Corp">
    <address>Silicon Valley</address>
    <people>
        <person>
            <name>John Doe</name>
            <age>30</age>
            <address>Jakarta</address>
            <birth_date>1993-01-01T00:00:00Z</birth_date>
        </person>
        <person>
            <name>Jane Smith</name>
            <age>28</age>
            <birth_date>1995-01-01T00:00:00Z</birth_date>
        </person>
    </people>
</company>
Decoded company name: Tech Corp

Custom Marshaling Example:
Task JSON:
{
    "name": "Long Task",
    "duration": "2h0m0s"
}
Decoded task duration: 2h0m0s

Binary Encoding Example:
Decoded message: {ID:1 Content:Hello, World! Time:2024-01-21 11:57:22.123456789 +0700 WIB}

Tips

  • Gunakan struct tags
  • Handle error dengan baik
  • Validasi input
  • Perhatikan performa
  • Pilih format yang sesuai kebutuhan