As per the docs: https://golang.org/pkg/encoding/json/#Marshal

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.

The value AAAAAQID is a base64 representation of your byte slice - e.g.

b, err := base64.StdEncoding.DecodeString("AAAAAQID")
if err != nil {
    log.Fatal(err)
}

fmt.Printf("%v", b)
// Outputs: [0 0 0 1 2 3]
Answer from elithrar on Stack Overflow
🌐
ITNEXT
itnext.io › welcome-to-just-enough-go-7dbef7e30188
Tutorial: How to work with JSON data in Go | by Abhishek Gupta | ITNEXT
October 5, 2019 - Given JSON in form of a byte array, Unmarshal stores the JSON parsing result to a pointer of the Go data type you specify (typically a struct)
Discussions

Marshaling JSON []byte as strings in Go - Stack Overflow
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 e... More on stackoverflow.com
🌐 stackoverflow.com
go - How to convert []byte slice into JSON GOLANG - Stack Overflow
Communities for your favorite technologies. Explore all Collectives · Stack Overflow for Teams is now called Stack Internal. Bring the best of human thought and AI automation together at your work More on stackoverflow.com
🌐 stackoverflow.com
Json encode byte array as hex string instead of base64
I’m trying to marshal an interface{} object to json format and print it to a nicer view, it’s almost OK except for byte array. I knew that by default 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 ... More on forum.golangbridge.org
🌐 forum.golangbridge.org
0
0
March 17, 2022
proposal: encoding/json: add a function to report whether a []byte represents a JSON array before unmarshal
Problem statement Many web applications utilize JSON encoding as its primary data exchange format. Among these, some applications may even accept different JSON schemes as an acceptable argument fo... More on github.com
🌐 github.com
6
May 31, 2022
Top answer
1 of 3
12

If []byte really is what you want, use json.RawMessage, which is of type []byte, but also implements the methods for JSON parsing. I believe this may be what you want, as it will accept whatever ends up in data. Of course, you then have to manually parse Data to figure out just what actually IS in there.

One possible bonus is that this skips any heavy parsing because it just copies the bytes over. When you want to use this data for something, you use a []interface{}, then use a type switch to use individual values.

https://play.golang.org/p/og88qb_qtpSGJ

package main

import (
    "encoding/json"
    "fmt"
)

type Obj struct {
    Id   string          `json:"id"`
    Data json.RawMessage `json:"data"`
}

func main() {
    byt := []byte(`{"id":"someID","data":["str1","str2", 1337, {"my": "obj", "id": 42}]}`)

    var obj Obj
    if err := json.Unmarshal(byt, &obj); err != nil {
        panic(err)
    }

    fmt.Printf("%+v\n", obj)
    fmt.Printf("Data: %s\n", obj.Data)

    // use it
    var d []interface{}
    if err := json.Unmarshal(obj.Data, &d); err != nil {
        panic(err)
    }
    fmt.Printf("%+v\n", d)

    for _, v := range d {
        // you need a type switch to deterine the type and be able to use most of these
        switch real := v.(type) {
        case string:
            fmt.Println("I'm a string!", real)
        case float64:
            fmt.Println("I'm a number!", real)
        default:
            fmt.Printf("Unaccounted for: %+v\n", v)
        }

    }
}
2 of 3
7

My first recommendation would be for you to just use []string instead of []byte if you know the input type is going to be an array of strings.

If data is going to be a JSON array with various types, then your best option is to use []interface{} instead - Go will happily unmarshal the JSON for you and you can perform checks at runtime to cast those into more specific typed variables on an as-needed basis.

🌐
Stack Overflow
stackoverflow.com › questions › 77905804 › how-to-convert-byte-slice-into-json-golang
go - How to convert []byte slice into JSON GOLANG - Stack Overflow
learning marshaling unmarshalling with a single dimensional byte is what i have encountered till date as learning. Please help me to understands the basics as i come from PHP JAVASCRIPT background multidimensional array concept is not similar to this ... use var jsonData map[string]interface{} err := json.Unmarshal(bytt, &jsonData) if err != nil { fmt.Println("Error:", err) return } // Now jsonData is a map containing the parsed JSON structure fmt.Println(jsonData)
🌐
ZetCode
zetcode.com › golang › json
Working with JSON in Go
Since json_data is a byte array, we convert it to a string with the string function.
🌐
Go
go.dev › play › p › P-BM9QdYjG
Go Playground - The Go Programming Language
Common problems companies solve with Go · Stories about how and why companies use Go
🌐
Dot Net Perls
dotnetperls.com › json-go
Go - JSON Example: Marshal, Unmarshal - Dot Net Perls
February 18, 2023 - package main import ( "encoding/json" "fmt" ) type Result struct { Positions []int } func main() { // This JSON contains an int array. text := "{\"Positions\": [100, 200, 300, -1]}" // Get bytes. bytes := []byte(text) // Unmarshal JSON to Result struct. var result Result json.Unmarshal(bytes, ...
Find elsewhere
🌐
Go Forum
forum.golangbridge.org › getting help
Json encode byte array as hex string instead of base64 - Getting Help - Go Forum
March 17, 2022 - I’m trying to marshal an interface{} object to json format and print it to a nicer view, it’s almost OK except for byte array. I knew that by default 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 value.
🌐
GitHub
github.com › golang › go › issues › 53170
proposal: encoding/json: add a function to report whether a []byte represents a JSON array before unmarshal · Issue #53170 · golang/go
May 31, 2022 - As a solution for this, I propose the implementation of a new exported function on pkg encoding/json to inform whether a raw []byte represents a JSON array (i.e. is a valid JSON and starts with [).
Author: golang
🌐
GitHub
gist.github.com › nikravi › e4812ed46ad77d8d2aee60faddd205df
Golang bytearray hex json representation, Playground: https://play.golang.org/p/fO7lmZ5WjWq · GitHub
Save nikravi/e4812ed46ad77d8d2aee60faddd205df to your computer and use it in GitHub Desktop. Download ZIP · Golang bytearray hex json representation, Playground: https://play.golang.org/p/fO7lmZ5WjWq · Raw · hexByteArray.go · This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below.
🌐
Go by Example
gobyexample.com › json
Go by Example: JSON
Go offers built-in support for JSON encoding and decoding, including to and from built-in and custom data types · We’ll use these two structs to demonstrate encoding and decoding of custom types below
🌐
Reddit
reddit.com › r/golang › why the heck am i getting an empty byte array trying to read a simple json file?
r/golang on Reddit: Why the heck am I getting an empty byte array trying to read a simple json file?
September 9, 2022 -

Hi, I'm new-ish to golang, formerly a self-taught python hack. I can not figure out why I'm unable to read this (rather large ~130mb) json file. I'm really at my wits end here. Please help me understand whats going on if you can!

Here is an image showing a nil value of b at the breakpoint after I've tried to unmarshal the json file.

https://imgur.com/a/szpp4Ih

I did edit out my system name in the photo.

Here is the code:

func Jsp() {
var b []byte
jsonFile, err := os.Open(".../Downloads/drug-label-0008-of-0011.json")
if err != nil {
fmt.Println(err)
}
bytes, err := ioutil.ReadAll(jsonFile)
if err != nil {
fmt.Println(err)
}
json.Unmarshal(bytes, &b)
fmt.Println(b)
}

Top answer
1 of 2
31

According to the docs, a []byte will be encoded as a Base64 string.

"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."

So I think that you may need to make your struct implement the Marshaler interface by implementing your own MarshalJSON method that makes a more desirable JSON array encoding out of your []uint8.

Take this example:

import "fmt"
import "encoding/json"
import "strings"

type Test struct {
    Name  string
    Array []uint8
}

func (t *Test) MarshalJSON() ([]byte, error) {
    var array string
    if t.Array == nil {
        array = "null"
    } else {
        array = strings.Join(strings.Fields(fmt.Sprintf("%d", t.Array)), ",")
    }
    jsonResult := fmt.Sprintf(`{"Name":%q,"Array":%s}`, t.Name, array)
    return []byte(jsonResult), nil
}

func main() {
    t := &Test{"Go", []uint8{'h', 'e', 'l', 'l', 'o'}}

    m, err := json.Marshal(t)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Printf("%s", m) // {"Name":"Go","Array":[104,101,108,108,111]}
}

http://play.golang.org/p/Tip59Z9gqs


Or maybe a better idea would be to make a new type that has []uint8 as its underlying type, make that type a Marshaler, and use that type in your struct.

import "fmt"
import "encoding/json"
import "strings"

type JSONableSlice []uint8

func (u JSONableSlice) MarshalJSON() ([]byte, error) {
    var result string
    if u == nil {
        result = "null"
    } else {
        result = strings.Join(strings.Fields(fmt.Sprintf("%d", u)), ",")
    }
    return []byte(result), nil
}

type Test struct {
    Name  string
    Array JSONableSlice
}

func main() {
    t := &Test{"Go", []uint8{'h', 'e', 'l', 'l', 'o'}}

    m, err := json.Marshal(t)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Printf("%s", m) // {"Name":"Go","Array":[104,101,108,108,111]}
}

http://play.golang.org/p/6aURXw8P5d

2 of 2
0

Here's another way, instead of using the slice []uint8, use the array [...]uint8:

marshal1, _ := json.Marshal([]uint8{32}) //"IA=="
marshal2, _ := json.Marshal([...]uint8{32}) //[32]

Also:

data := []uint8{32}
marshal, _ := json.Marshal((*[1]uint8)(data)) //after go1.17
marshal, _ := json.Marshal(*(*[1]uint8)(unsafe.Pointer(&data[0]))) //not recommended

Because go only treats byte slices specially (at least in the current version 1.23):

func newSliceEncoder(t reflect.Type) encoderFunc {
    // Byte slices get special treatment; arrays don't.
    if t.Elem().Kind() == reflect.Uint8 {
        p := reflect.PointerTo(t.Elem())
        if !p.Implements(marshalerType) && ! p.Implements(textMarshalerType) {
            return encodeByteSlice
        }
    }
    enc := sliceEncoder{newArrayEncoder(t)}
    return enc.encode
}
🌐
Thedeveloperblog
thedeveloperblog.com › go › json-go
Golang JSON Example: Marshal, Unmarshal - The Developer
Use the encoding/json library to convert Go objects to JSON. Call Marshal and Unmarshal. | TheDeveloperBlog.com
🌐
Envato Tuts+
code.tutsplus.com › home › coding fundamentals
JSON Serialization With Golang | Envato Tuts+
February 21, 2018 - You deserialize a slice of bytes into a Golang value using the Unmarshal() function. It's that simple. The following terms are equivalent in the context of this article: ... I prefer serialization because it reflects the fact that you convert ...