Go 中的部分 JSON 解码和更新
在某些场景下,仅解码和更新 JSON 对象的特定值时会出现常见问题,特别是当完整的对象结构未知时。 Go中的标准encoding/json包会截断结构体中未提供的字段,导致数据丢失。
使用json.RawMessage的解决方案
这个问题的解决方案是将自定义结构与 json.RawMessage 结合起来。这种方法允许我们将整个数据保存到原始字段中以进行编码/解码。
Go 中的 json.RawMessage 类型是一个 []byte 值,可以保存任意 JSON 数据。对于这样的情况很有用,我们只知道 JSON 结构的一部分,并希望保留未知部分。
示例代码
package main import ( "encoding/json" "log" ) type Color struct { Space string raw map[string]json.RawMessage } 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 } 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) } func main() { before := []byte(`{"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10}}`) log.Println("before: ", string(before)) // decode color := new(Color) err := json.Unmarshal(before, color) if err != nil { log.Fatal(err) } // modify fields of interest color.Space = "RGB" // encode after, err := json.Marshal(color) if err != nil { log.Fatal(err) } log.Println("after: ", string(after)) }
输出
before: {"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10}} after: {"Point":{"Y":255,"Cb":0,"Cr":-10},"Space":"RGB"}
此解决方案允许我们仅解码和更新特定值(在在本例中为 Space),同时保留 JSON 对象中的所有其他未知数据。需要注意的是,这种方法不会保留输出中的键顺序或缩进。
以上是如何在 Go 中部分解码和更新 JSON 对象?的详细内容。更多信息请关注PHP中文网其他相关文章!