处理 JSON 数据时,有时需要仅修改特定值而不丢失现有结构。如果您不知道 JSON 对象的整个结构,这可能会很有挑战性,因为 Go 的encoding/json 包会截断目标结构中未包含的字段。
本文探讨了一种利用常规结构组合的技术和 json.RawMessage 实现部分解码和更新,且不会丢失未知信息。
部分解码的关键解码是将整个 JSON 数据保存在原始字段(例如,map[string]json.RawMessage)中,并有选择地将特定字段解组到结构中。它是这样完成的:
import "encoding/json" 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 }
这里,UnmarshalJSON 将整个 JSON 数据检索到 c.raw,然后将 Space 字段解组到 c.Space。
部分解码 JSON 数据后,您可以将特定字段修改为需要。
修改已知字段后,您需要将更新的 Color 结构编组回 JSON。为了保留现有结构并避免截断,您可以编写自定义 MarshalJSON 方法:
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) }
在 MarshalJSON 中,您对修改后的 Space 字段进行编组,然后在执行最终编组之前将其嵌入到原始映射中。
该技术允许您修改 JSON 数据中的特定值而不丢失未知信息,使其适合适用于完整 JSON 结构不可用或可能发生更改的场景。
以上是如何在 Go 中部分解码和更新 JSON 数据而不丢失未知字段?的详细内容。更多信息请关注PHP中文网其他相关文章!