1. ホーム
  2. json

[解決済み] JSONとunexportedフィールドの扱いについて

2023-08-09 18:20:14

質問

unexported フィールドがエンコーディング/json によって含まれない技術的な理由はありますか? そうではなく、任意の決定である場合、unexported であっても含めるための追加のバックドア オプション (たとえば '+') がある可能性はありますか?

この機能を得るためにクライアントコードにエクスポートを要求することは、特に小文字がカプセル化を提供している場合、またはマーシャル構造の決定がそれらの設計よりもずっと後になる場合、残念な感じがします。

人々はどのようにこれに対処しているのでしょうか?ただすべてをエクスポートするのですか?

また、フィールド名をエクスポートすると、推奨されるイディオムに従うことが難しくなりませんか。構造体 X がフィールド Y を持つ場合、アクセッサメソッド Y() を持つことはできないと思います。Y へのインターフェイスのアクセスを提供したい場合、ゲッターの新しい名前を考えなければなりませんし、どうしたって http://golang.org/doc/effective_go.html#Getters

どのように解決するのですか?

技術的な理由があります。jsonライブラリは、エクスポートされない限り、reflectを使用してフィールドを表示する権限を持っていません。パッケージは、それ自身のパッケージ内の型のエクスポートされていないフィールドを見ることができるだけです。

この問題に対処するためにできることは、エクスポートされたフィールドを持つ未エクスポートの型を作ることです。Jsonは問題なく渡された場合、unexported型にアンマーシャルしますが、APIドキュメントには表示されないでしょう。次に、エクスポートされた型を作成して、その型を埋め込むことができる。このエクスポートされた型には json.Marshalerjson.Unmarshaler というインターフェイスがあります。

注意:全てのコードは未テストであり、コンパイルすらできないかもしれません。

type jsonData struct {
    Field1 string
    Field2 string
}

type JsonData struct {
    jsonData
}

// Implement json.Unmarshaller
func (d *JsonData) UnmarshalJSON(b []byte) error {
    return json.Unmarshal(b, &d.jsonData)
}

// Getter
func (d *JsonData) Field1() string {
    return d.jsonData.Field1
}