How to force go to encode `[8]byte` as hex when marshaling to json

Viewed 2041

By default byte slices are marshalled as Base64 strings and byte arrays are converted as is:

func main() {
    type Foo struct {
        ByteSlice []byte
        ByteArray [6]byte
    }

    foo := Foo {
        ByteSlice: []byte{0, 0, 0, 1, 2, 3},
        ByteArray: [6]byte{0, 0, 0, 1, 2, 3},
    }
    text, _ := json.Marshal(foo)
    fmt.Printf("%s", text)
}

Output:

{"ByteSlice":"AAAAAQID","ByteArray":[0,0,0,1,2,3]}

Is there a way to use hex string conversion for byte slices?

3 Answers

You could customize JSON serialization if you define a custom type. I've substitute []byte for instance:

Output:

{"ByteSlice":"000000010203","ByteArray":[0,0,0,1,2,3]}

Code:

package main

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

type MyByteSlice []byte

func (m MyByteSlice) MarshalJSON() ([]byte, error) {
    return json.Marshal(hex.EncodeToString(m))
}

func main() {
    type Foo struct {
        ByteSlice MyByteSlice
        ByteArray [6]byte
    }

    foo := Foo {
        ByteSlice: []byte{0, 0, 0, 1, 2, 3},
        ByteArray: [6]byte{0, 0, 0, 1, 2, 3},
    }

    text, _ := json.Marshal(foo)
    fmt.Printf("%s\n", text)
}

Is there a way to use hex string conversion for byte slices?

No there is not.

You have to encode it yourself. Either into a new struct with a string field or by writing your own UnmarshalJSON method as described in package json's doc.

there is no easy way to change golang default bytes encoder.

  1. use struct Foo custom marshal and unmarshal, this way can fit most situation, but when we have base type like a "type Hash [32]byte", and use it in different struct. then we must write marshal and unmarshal for all the struct.

  2. like the Answer above, define a new type for cutom marshal, but the func must use pointer not value type:

type Hash []byte

func (h *Hash) MarshalJSON() ([]byte, error) {
    ...
}
func (h *Hash) UnmarshalJSON(b []byte) error {
    ...
}

and change your struct define:

type Foo struct {
    ByteSlice *Hash
    ByteArray [6]byte
}

you must use pointer define, otherwise will not use custom marshal and unmarshal

Related