2012-06-20 18 views
40

エンコードされていないフィールドがencoding/jsonに含まれていない技術的な理由はありますか?そうでなければ、それは恣意的な決定ですが、アンカバーされているにもかかわらず、追加のバックドアオプション( '+')を含めることができますか?JSONと非公開フィールドの処理

この機能を使用するためにエクスポートするクライアントコードを要求することは、特に小文字がカプセル化を提供している場合、またはマーシャル構造体の決定がデザインのものよりも遅れている場合には不幸です。

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

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

答えて

64

技術的な理由があります。 jsonライブラリは、エクスポートされない限り、リフレクトを使用してフィールドを表示する権限を持ちません。パッケージは、独自のパッケージ内のタイプの非通知フィールドのみを表示することができます

あなたの問題に対処するために、エクスポートされたフィールドで非表示の型を作成することができます。 Jsonは、問題なく渡されれば、非通知型に非整列化されますが、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 
} 
+0

記録のために、私は "json.Unmarshal(b、&d.jsonData)"を使用してUnmarshallする必要がありました。私は間違ったことをしたのか、それとも期待されたのでしょうか? – Derek

+0

@Derek、ありがとう、私は私の答えを更新しました。私が言ったように、コードはテストされていませんでした。私は 'UnmarshalJSON()'メソッドでreturn文も忘れてしまったようです。私もこれを修正しました。 –

+3

私はショーに少し遅れていますが、上記の作品は、フィールド1とフィールド2 _are_エクスポートされている間。そのパッケージの外にあるJsonData(大文字J付き)のField1とField2を読み書きすることができます。したがって、これは理論的にはクールですが、実際にはタイプとフィールドの両方をエクスポートする以外に何もしません。 – davidjosepha

41

スティーブンスの回答が完了しました。

type Whatever struct { 
    SomeField int `json:"some_field"` 
} 

そのようにして、フィールドSomeFieldのためのキーを生成どのような「some_field」をマーシャリング:さておき、あなたが本当にしたいすべてがあなたのJSONで小文字のキーであれば、以下のように、手動でキー名を指定することができますよう(あなたのjsonに "SomeField"を持つ代わりに)。

未記入フィールドを残しておきたい場合は、MarshalJSON() ([]byte, error)のメソッドを定義してjson.Marshalerインターフェイスを実装することもできます。

type Whatever struct { 
    someField int 
} 

func (w Whatever) MarshalJSON() ([]byte, error) { 
    return json.Marshal(struct{ 
     SomeField int `json:"some_field"` 
    }{ 
     SomeField: w.someField, 
    }) 
} 
ご希望の場合は、また map[string]interface{}を使用することができますので、少し面倒なことができ

これを行う1つの方法は、単純にこのように、アンエクスポートフィールドのバージョンを輸出しているリテラルという構造体を使用することです精度の損失を引き起こし、 interface{}をマーシャリングすると、いくつかの注意点があり、フロートにマーシャル uint64のようなものを行うことに留意すべきであるしかし
func (w Whatever) MarshalJSON() ([]byte, error) { 
    return json.Marshal(map[string]interface{}{ 
     "some_field": w.SomeField, 
    }) 
} 

。 (すべてのコードはテストされていません)

+0

技術的には、Javascriptのすべての数字は浮動小数点数です。 –

+16

JSONはJavaScriptではありません。 JSON仕様では、どの文字列が有効ではないかを示す文字だけを示しています。 876234958273645982736459827346598237465923847561203947812435968234659827346のような数値は、JavaScriptで理解できない場合でもJSONで有効です。実際の世界の例では、Twitter APIはツイートIDを64ビットの符号なし整数で表します。これはJavaScriptでは無効ですが、有効なJSONです。 – jorelli

+1

現在のところ、すべて真ですが、名前はまだJSONです。これは歴史的に "JavaScript Object Notation"の略です。あなたがNJSON(NewJSONかNotJavaScript)に名前を変更したいと思うそれらの驚くべきビットの1つ:) – quetzalcoatl

関連する問題