LoginSignup
1
0

More than 3 years have passed since last update.

Go の json.Marshal の思いがけない仕様

Last updated at Posted at 2020-03-16

結論

json.Marshal は、uint8 型のスライスを base64 文字列にする。
int8 型だったり スライスじゃなくて配列だったりすると配列になるけど。

ソースコードと実行結果

golang
package main

import (
    "encoding/json"
    "fmt"
)

type S struct {
    U8Array  [3]uint8
    U8Slice  []uint8
    S8Array  [3]int8
    S8Slice  []int8
    U8SliceP *[]uint8
    PU8Slice []*uint8
    IFSlice []interface{}
}

func main() {
    a:=uint8(1)
    b:=uint8(2)
    c:=uint8(3)
    o := S{
        U8Array:  [3]uint8{1, 2, 3},
        U8Slice:  []uint8{1, 2, 3},
        S8Array:  [3]int8{1, 2, 3},
        S8Slice:  []int8{1, 2, 3},
        U8SliceP: &[]uint8{1, 2, 3},
        PU8Slice: []*uint8{&a, &b, &c},
        IFSlice: []interface{}{uint8(1),uint8(2),uint8(3)},
    }
    bytes, _ := json.Marshal(o)
    fmt.Println(string(bytes))
}

実行するとこうなる:

json
{
  "U8Array":[1,2,3],
  "U8Slice":"AQID",
  "S8Array":[1,2,3],
  "S8Slice":[1,2,3],
  "U8SliceP":"AQID",
  "PU8Slice":[1,2,3],
  "IFSlice":[1,2,3]
}

"AQID" について

base64 でデコードすると、下記の通り [1, 2, 3] になる。

ruby
require "base64"
Base64.decode64("AQID").bytes
# => [1, 2, 3]

まとめ

json.Marshal でシリアライズすると下表のようになる。

go上の型 json
uint8 の配列 数値の配列
uint8 のスライス base64文字列
int8 の配列 数値の配列
int8 のスライス 数値の配列
uint8 のスライスへのポインタ base64文字列
uint8 へのポインタのスライス 数値の配列
interface のスライスに uint8 だけを詰めたもの 数値の配列

思いがけない仕様で大変驚いた。
驚きは2点

  • uint8 のスライスが base64文字列になる点。
  • uint8スライス が base64文字列になるのに、uint8配列 は数値の配列になる点。
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0