在處理 JSON 資料時,通常需要在沒有物件完整結構的情況下存取和修改特定值。 Go 中的encoding/json 套件雖然提供了強大的解碼和編碼功能,但會截斷或忽略目標結構中未明確定義的欄位。這可能會導致重新編碼時丟失未知資訊。
為了克服這項挑戰,可以利用常規結構體和 json 的組合。 RawMessage實現部分解碼和更新。 json.RawMessage 表示原始 JSON 數據,允許保存任何 JSON 結構而無需解碼其特定形式。
在下面的程式碼片段中,Color 結構體是使用 Space 欄位和類型為 map[ 的原始欄位定義的字串]json.RawMessage。這樣可以儲存整個 JSON 對象,同時僅明確解組已知欄位 (Space)。
type Color struct { Space string raw map[string]json.RawMessage }
在解組過程中,UnmarshalJSON 方法提取 Space 欄位來自原始資料(如果存在)。完整的原始數據儲存在原始地圖中。
func (c *Color) UnmarshalJSON(bytes []byte) error { if err := json.Unmarshal(bytes, &c.raw); err != nil { return err } if space, ok := c.raw["Space"]; ok { if err := json.Unmarshal(space, &c.Space); err != nil { return err } } return nil }
更新值時,僅需修改已知欄位。在這種情況下,可以為 color.Space 指派一個新值。
編組期間,MarshalJSON 方法會擷取更新的空間值並將其儲存為 json.RawMessage 之前的原始映射中將整個物件編碼為 JSON。
func (c *Color) MarshalJSON() ([]byte, error) { bytes, err := json.Marshal(c.Space) if err != nil { return nil, err } c.raw["Space"] = json.RawMessage(bytes) return json.Marshal(c.raw) }
以下範例示範JSON 物件的部分解碼與更新:
before := []byte(`{"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10}}`) // Decode color := new(Color) err := json.Unmarshal(before, color) // Modify the Space field color.Space = "RGB" // Encode after, err := json.Marshal(color)
輸出將會是:
{"Point":{"Y":255,"Cb":0,"Cr":-10},"Space":"RGB"}
以上是如何在Go中間分解碼和更新JSON資料而不丟失未知資訊?的詳細內容。更多資訊請關注PHP中文網其他相關文章!