Go では、JSON データを操作する場合、未知のフィールドにアクセスするためにデータを部分的にアンマーシャリングする必要がある場合があります。または、異種の JSON 構造を処理します。ただし、このプロセスでは二重のアンマーシャリングが発生し、非効率になる可能性があります。この記事では、json.RawMessage を使用してこの問題を回避する解決策を紹介します。
Web ソケット接続がさまざまな種類の JSON メッセージを送信し、それらを既知の構造体にアンマーシャリングするシナリオを考えてみましょう。従来のアプローチでは、JSON を汎用のマップ[文字列]インターフェース{}にアンマーシャリングし、目的のキーを検索して、値を目的のタイプにキャストしようとします。ただし、ネストされた JSON 構造を操作する場合、このアプローチは失敗する可能性があります。
この問題を解決するには、値をインターフェイス{}にアンマーシャリングする代わりに、値を json.RawMessage にアンマーシャリングします。これにより、型情報を失うことなく生の JSON データにアクセスできるようになります。その後、switch ステートメントで、生の JSON データを再マーシャリングすることなく、目的の構造体に直接アンマーシャリングできます。
import ( "encoding/json" "fmt" ) type Ping struct { Ping string `json:"ping"` } type Ack struct { Messages []Message `json:"messages"` } type Message string func main() { testJSON := []byte(`{"ack":{"messages":["Hi there","Hi again"]}}`) var myAck = Ack{} var myMap map[string]json.RawMessage err := json.Unmarshal(testJSON, &myMap) if err != nil { fmt.Println("error unmarshalling: ", err) } for k, v := range myMap { fmt.Printf("key: %s, value: %s \n", k, v) switch k { case "ping": fmt.Println(k, " is a ping", v) case "ack": fmt.Println(k, " is an ack containing a message list") err = json.Unmarshal(v, &myAck) if err != nil { fmt.Println("unmarshal error", err) } else { fmt.Println("New ack object: ", myAck) } default: fmt.Printf("%s is of a type (%T) I don't know how to handle", k, v) } } }
このアプローチにより、マーシャリングとアンマーシャリングの冗長な手順が回避されます。これにより、異種構造の JSON データをより効率的かつ簡単に処理できるようになります。
以上が異種の JSON 構造を処理する場合、json.RawMessage は Go での二重アンマーシャリングをどのように防ぐことができますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。