7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

privateの構造体をjson.Marshalした時に空でreturnされる

Last updated at Posted at 2019-04-13

概要

同package内でのみアクセスできる(private)構造体を json.Marshal した時に戻り値が空になる。

事象

privateの構造体を用意する

pkg/User.go
package pkg

type User struct {
	id    string
	name  string
	token string
}

func (u User) GetId() string {
	return u.id
}

func (u User) GetName() string {
	return u.name
}

func (u User) GetToken() string {
	return u.token
}

func New(id, name, token string) *User {
	return &User{id, name, token}
}

対象の構造体(User.go)をjson.Marshalする。

test.go
package main

import (
	"encoding/json"
	"fmt"
	"work/pkg"
)

func main() {
	user := pkg.New("0001", "test-user", "abcdefg")
	fmt.Println(user)

	userjson, err := json.Marshal(&user)
	if err != nil {
		fmt.Errorf("error marshal:", err)
	}
	fmt.Println(string(userjson))
}

実行結果は以下の通り、空で出力される

&{0001 test-user abcdefg}
{}

なんとなく、察してはいたけれどjson.Marshalはprivateな値は対象にしてくれない模様…
先頭文字を直してpublicにしようか迷ったがオブジェクト指向っぽく作りたかったため、今回はMarshalJSONで誤魔化す事にした。

pkg/User.go
package pkg

import "encoding/json"

type User struct {
	id    string
	name  string
	token string
}

func (u User) GetId() string {
	return u.id
}

func (u User) GetName() string {
	return u.name
}

func (u User) GetToken() string {
	return u.token
}

func New(id, name, token string) *User {
	return &User{id, name, token}
}

/* json.Marshalする時に各項目をGetする処理を追加 */
func (u *User) MarshalJSON() ([]byte, error) {
	v, err := json.Marshal(&struct {
		Id    string
		Name  string
		Token string
	}{
		Id:    u.GetId(),
		Name:  u.GetName(),
		Token: u.GetToken(),
	})
	return v, err
}

再度、実行する

&{0001 test-user abcdefg}
{"Id":"0001","Name":"test-user","Token":"abcdefg"}

追記

Getメソッドが不要な場合もあるので、下の様なやり方でも可能。
Goの場合だとこの方がやりやすかな??

pkg/User.go
package pkg

import (
	"encoding/json"
)

type User struct {
	id    string
	name  string
	token string
}

func New(id, name, token string) *User {
	return &User{id, name, token}
}

/* 構造体から値を取得 */
func (u *User) MarshalJSON() ([]byte, error) {
	v, err := json.Marshal(&struct {
		Id    string
		Name  string
		Token string
	}{
		Id:    u.id,
		Name:  u.name,
		Token: u.token,
	})
	return v, err
}

所感

値にjsonパラメータを設定する際にprivateでも取得できる様な設定方法があるのかは随時調査して行く予定です。
jsonに変換する構造体自体をpublicで作るべきなのかは、正直分からず…
もっといい実装方法をご存知の方がいらっしゃいましたら教えて頂けると幸いです。

そもそも、Goではパッケージ外部からアクセスできない構造体をprivateと読んでいいのかも謎です。
(java脳ですみません。。。)

7
3
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
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?