I have a struct containing strings as []byte fields which I'd like to encode into JSON. However, the generated JSON contains a non expected string representation of the slice contents. Here is an example of what I refer:
package main
import (
"fmt"
"encoding/json"
)
type Msg struct {
Content []byte
}
func main() {
helloStr := "Hello"
helloSlc := []byte(helloStr)
fmt.Println(helloStr, helloSlc)
obj := Msg{helloSlc}
json, _ := json.Marshal(obj)
fmt.Println(string(json))
}
This produces the following output:
Hello [72 101 108 108 111]
{"Content":"SGVsbG8="}
What kind of conversion is the json.Marshal() method performing to the []byte encoded string. How can I generate a JSON with the original content of my string {"Content":"Hello"}?
JSON does not support that. Use Base64. That is your library supporting it, not JSON itself. The byte array wont be stored as byte array in the JSON, JSON is a text format meant to be human readable.
To encode JSON data we use the Marshal function. Only data structures that can be represented as valid JSON will be encoded: JSON objects only support strings as keys; to encode a Go map type it must be of the form map[string]T (where T is any Go type supported by the json package).
What is marshaling in Go? Encoding Go objects to JSON format is known as marshaling. We can use the Marshal function to convert Go objects to JSON. The Marshal function comes with the following syntax. func Marshal(v interface{}) ([]byte, error)
Golang UnmarshalUnmarshal is the contrary of marshal. It allows you to convert byte data into the original data structure. In go, unmarshaling is handled by the json.
We mostly deal with complex objects or arrays when working with JSON, but data like 3, 3.1412 and "birds" are also valid JSON strings. We can unmarshal these values to their corresponding data type in Go by using primitive types: We saw earlier that Go uses convention to determine the attribute name for mapping JSON properties.
This isn’t much different from structs. We just need to pass the slice or array to the json.Marshal function, and it will encode data like you expect: We can use maps to encode unstructured data. The keys of the map need to be strings, or a type that can convert to strings. The values can be any serializable type.
However the Go standard library encoding/json package allows us to encode any data type into a JSON string. Let’s see some of the examples and how the json encoding works on some of the basic Go data types and how you can marshal json. Here’s the definition of the json Marshal in the json encoding package
In the above, tags are defined for every field, which tells the Marshal method to convert ID as obj.id in the resulting JSON string. Here omitempty means that skip this field if it is nil or zero value for any data type. To Marshal Go object, we use Marshal (v interface {}) method, which returns the slice of bytes for the converted JSON string.
A []byte
is marshalled as base64 encoded string. From the documentation:
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.
These values are decoded properly when unmarshalled.
The reason why this is done is that JSON does not have a native representation for raw bytes. See this question for a detailed explanation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With