Home >Backend Development >Golang >Why does Go's `json.Marshal` convert []byte to a base64 string, and how can I fix it?

Why does Go's `json.Marshal` convert []byte to a base64 string, and how can I fix it?

Linda Hamilton
Linda HamiltonOriginal
2024-12-22 00:04:17682browse

Why does Go's `json.Marshal` convert []byte to a base64 string, and how can I fix it?

Marshaling []byte to JSON: Decoding Mysterious Strings

When attempting to convert a byte slice ([]byte) to JSON format, developers often encounter unexpected string representations. This article delves into the reasons for this behavior and provides a solution for marshaling byte slices accurately.

The Puzzling Case

Consider the following code snippet:

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

func main() {
    type ColorGroup struct {
        ByteSlice    []byte
        SingleByte   byte
        IntSlice     []int
    }
    group := ColorGroup{
        ByteSlice:  []byte{0, 0, 0, 1, 2, 3},
        SingleByte: 10,
        IntSlice:   []int{0, 0, 0, 1, 2, 3},
    }
    b, err := json.Marshal(group)
    if err != nil {
        fmt.Println("error:", err)
    }
    os.Stdout.Write(b)
}

When executed, this code outputs:

{"ByteSlice":"AAAAAQID","SingleByte":10,"IntSlice":[0,0,0,1,2,3]}

Intriguing, the ByteSlice field, which should contain an array of bytes, has been rendered as "AAAAAQID".

Unraveling the Mystery

The explanation lies in the documentation for the json package:

Array and slice values encode as JSON arrays, except that []byte encodes as a base64-encoded string, and a nil slice encodes as the null JSON object.

In this case, the ByteSlice field, an array of bytes, is not encoded as a JSON array but rather as a base64-encoded string.

A Solution: Base64 Decoding

To marshal []byte data to JSON as expected, it's necessary to decode the base64 representation. Here's an updated version of the code:

package main

import (
    "encoding/base64"
    "encoding/json"
    "fmt"
    "os"
)

func main() {
    type ColorGroup struct {
        ByteSlice    []byte
        SingleByte   byte
        IntSlice     []int
    }
    group := ColorGroup{
        ByteSlice:  []byte{0, 0, 0, 1, 2, 3},
        SingleByte: 10,
        IntSlice:   []int{0, 0, 0, 1, 2, 3},
    }
    // Decode ByteSlice from base64 before marshaling
    decodedByteSlice, err := base64.StdEncoding.DecodeString(string(group.ByteSlice))
    if err != nil {
        fmt.Println("error:", err)
    }
    group.ByteSlice = decodedByteSlice
    b, err := json.Marshal(group)
    if err != nil {
        fmt.Println("error:", err)
    }
    os.Stdout.Write(b)
}

Now, the resulting JSON output correctly represents the ByteSlice field as an array of bytes:

{"ByteSlice":[0,0,0,1,2,3],"SingleByte":10,"IntSlice":[0,0,0,1,2,3]}

The above is the detailed content of Why does Go's `json.Marshal` convert []byte to a base64 string, and how can I fix it?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn