动态增强未知结构的 JSON 输出
简介
在 Go 中,可以增强通过将已知结构嵌入为匿名字段来进行 JSON 输出。但是,此技术仅适用于特定类型。本文探讨如何将此功能扩展到未知的结构或接口。
示例
考虑以下示例:
type example interface{} type Data struct { Name string } func printInterface(val interface{}) { example1 := struct { example Extra string }{ example: val, Extra: "text", } json.NewEncoder(os.Stdout).Encode(example1) } func main() { d := Data{Name: "name"} printInterface(&d) }
此代码打印以下 JSON :
{"example":{"Name":"name"},"Extra":"text"}
注意“名称”字段是如何包装在不必要的“示例”中的
解决方案1:通过反射生成动态类型
为了避免“示例”对象,我们需要在运行时生成动态类型。我们可以使用反射来创建一个嵌入未知接口并包含附加“Extra”字段的结构类型。
func printInterface(val interface{}) { t2 := reflect.StructOf([]reflect.StructField{ { Name: "X", Anonymous: true, Type: reflect.TypeOf(val), }, { Name: "Extra", Type: reflect.TypeOf(""), }, }) v2 := reflect.New(t2).Elem() v2.Field(0).Set(reflect.ValueOf(val)) v2.FieldByName("Extra").SetString("text") json.NewEncoder(os.Stdout).Encode(v2.Interface()) }
通过此更改,输出将变为:
{"Name":"name","Extra":"text"}
解决方案 2:编组和解组
另一种方法是编组接口,将其解组到映射中,添加附加字段,然后再次编组:
func printInterface(val interface{}) error { data, err := json.Marshal(val) if err != nil { return err } v2 := map[string]interface{}{} if err := json.Unmarshal(data, &v2); err != nil { return err } v2["Extra"] = "text" return json.NewEncoder(os.Stdout).Encode(v2) }
此方法产生与动态类型方法相同的输出。
结论
这里提出的两种解决方案都可以使用未知结构或接口的任意字段扩展 JSON 输出。基于反射的方法提供了类型安全的解决方案,而编组和解组技术更简单,但可能更慢。方法的选择取决于应用程序的具体要求。
以上是如何动态地将字段添加到未知 Go 结构的 JSON 输出?的详细内容。更多信息请关注PHP中文网其他相关文章!