2016-09-22 6 views
0

jsonをワイヤーで動かすのに苦労しています。ゴランのhttp応答の一部としてjsonbをエンコードする方法

http応答としてワイヤで送信する前に、構造体に追加する必要のあるPostgresデータベースにはjsonbフィールドがあります。

構造体のペイロードフィールドがstringの場合、マーシャリングはjsonを"{\"id\": \"3aa5fff0-ad91-41b1-84f0-d97f38e0e0f4\", \"user\": 1 }のようにエスケープします。

構造体のペイロードフィールドがjson.RawMessageの場合、marshallingはjsonをエスケープして(私が想像するように)base64でエンコードされたバイト列をエスケープします。

これは私がマーシャリングおよびHTTP応答ストリームに書いています構造体です:

type NestJobReturn struct { Status string `json:"status"` Nest json.RawMessage `json:"nest"` }

私はこの構造体のretインスタンスを構築し、それをプリントアウト。私は%vを使用している場合、それはバイトを示し、%sは、適切な、非エスケープJSON文字列としてそれを示しています

log("Value of ret.Nest: %v", ret.Nest) // Value of ret.Nest: [123 34 105 ... log("Value of ret.Nest as a string: %s", ret.Nest) // Value of ret.Nest as a string: {"id": "f053...

マーシャリングおよびI/Oはthusly行われます

js, _ := json.Marshal(ret) res.Header().Set("Content-Type", "application/json") res.Write(js)

クライアントは現在、このようなメッセージ全体を受信して​​います。

{"status":"ok","nest":"eyJpZCI6ICJmMD..."}

... "nest"の意図した値は、データベースのjsonbカラムの有効なjsonです。

アイデア?

+1

'配列とスライスの値はJSON配列としてエンコードされますが、[]バイトはbase64エンコードされた文字列としてエンコードされます。' 'json.RawMessage'は[]バイト型です – jsxqf

答えて

1

ネストされたフィールドをpointerjson.RawMessageとして定義する必要があります。あなたは、単に
js, _ := json.Marshal(&ret)


js, _ := json.Marshal(ret)を変更し、それが起動しなければならない代わりに、RET自身

のごRETへのポインタをマーシャリングする必要が

type NestJobReturn struct { 
    Status string   `json:"status"` 
    Nest *json.RawMessage `json:"nest"` 
} 

jsonStr := `{"type": "Object", "desc": "Simple nested object"}` 
raw := json.RawMessage(jsonStr) 

ret := NestJobReturn { 
    Status: "DONE", 
    Nest: &raw, 
} 

実施例https://play.golang.org/p/Ju7kgbawss

+0

これはうまくいきますが、[OfficialMailage ](https://golang.org/pkg/encoding/json/#example_RawMessage)は、RawMessageへのポインタを使用しないので、値として使用するように設計されていると思います。 – zevdg

+1

[this](https://github.com/golang/go/issues/6528)と[this](https://github.com/golang/go/issues/14493)のために、私は ' * json.RawMessage'。コンテナ( 'struct')を' value'または 'pointer'として' json.Marshal'に渡すと、同じJSON文字列を返します。 [遊び場](https://play.golang.org/p/xeSaF9dXk9) – putu

+0

ありがとうございました、それらの問題のリンクは超素晴らしいです!私はなぜあなたの修正が働いたのか理解していましたが、私はなぜ私の頭の周りに頭をラッピングするのに問題がありました。これは私のために多くのものをクリアします。 – zevdg

1

ワーキング。
playground link

はいっそのこと、あなたはどちらかがI Putu Susila's answerと一緒に行くかは常にマーシャル自体正しくこの非常にわずかに微調整バージョン

type RawMessage []byte 

// MarshalJSON returns m as the JSON encoding of m. 
func (m RawMessage) MarshalJSON() ([]byte, error) { 
    return m, nil 
} 

// UnmarshalJSON sets *m to a copy of data. 
func (m *RawMessage) UnmarshalJSON(data []byte) error { 
    if m == nil { 
     return errors.New("json.RawMessage: UnmarshalJSON on nil pointer") 
    } 
    *m = append((*m)[0:0], data...) 
    return nil 
} 

次に、あなたの構造体でjson.RawMessageを交換することによって、あなたのstruct馬鹿証拠を作ることができます。
playground link

これは、この癖(I Putu Susila's commentのリンク礼儀)のためにthe github issueで提案された修正ですが、コンセンサスは、これはRawMessageが振る舞うべき方法であっても、彼らが起因して、今それを変更することはできませんということですgo標準ライブラリの互換性保証。幸いにも、標準ライブラリで修正できなかったからといって、自分のコードベースで修正できないというわけではありません。

関連する問題