gpt4 book ai didi

解码 json 的 Golang 类型转换/断言问题

转载 作者:数据小太阳 更新时间:2023-10-29 03:06:11 24 4
gpt4 key购买 nike

package main

import (
"fmt"
"encoding/json"
"reflect"
)

type GeneralConfig map[string]interface{}

var data string = `
{
"key":"value",
"important_key":
{"foo":"bar"}
}`

func main() {
jsonData := &GeneralConfig{}
json.Unmarshal([]byte(data), jsonData)

fmt.Println(reflect.TypeOf(jsonData)) //main.GeneralConfig

jsonTemp := (*jsonData)["important_key"]
fmt.Println(reflect.TypeOf(jsonTemp)) //map[string]interface {}

//newGeneralConfig := GeneralConfig(jsonTemp)
//cannot convert jsonTemp (type interface {}) to type GeneralConfig:
//need type assertion

newGeneralConfig := jsonTemp.(GeneralConfig)
//fmt.Println(reflect.TypeOf(newGeneralConfig))
//panic: interface conversion: interface {} is map[string]interface {},
//not main.GeneralConfig

}

可在 the playground 获得

我知道我可以使用嵌套结构代替 GeneralConfig,但这需要我知道有效负载的确切结构,即它不适用于不同的键(我会锁定到“important_key”)。

当我不知道“important_key”的值是什么时,是否有 golang 解决方法?我说 golang,因为如果可能的话,可以要求所有“important_keys”有一个不变的父键,这可以解决这个问题。

总而言之,给定一个任意的 json 对象,必须有一种方法可以遍历它的键,如果值是自定义类型,则将该值转换为该类型。现在看来,如果我使用类型转换,它会告诉我类型是 interface{} 并且我需要使用类型断言;但是,如果我使用类型断言,它会告诉我 interface{}map[string]interface{} 而不是 main.GeneralConfig

最佳答案

我同意关于尝试利用传入 JSON 的预期结构来编写定义明确的结构的评论,但无论如何我都会尝试回答这个问题。

从您所看到的打印内容与您所看到的错误消息中可以看出,编译器对类型的了解少于运行时,因为运行时可以查看实际值。为了让编译器跟上速度,我们必须 (i) 断言 (*jsonData)["important_key"] 是一个 map[string]interface{} ——编译器只知道它是一个interface{}——然后​​ (ii) 将其类型转换为 GeneralConfig 类型。见:

package main

import (
"fmt"
"encoding/json"
)

type GeneralConfig map[string]interface{}

func main() {
jsonStruct := new(GeneralConfig)
json.Unmarshal([]byte(`{"parent_key": {"foo": "bar"}}`), jsonStruct)
fmt.Printf("%#v\n", jsonStruct)
// => &main.GeneralConfig{"parent_key":map[string]interface {}{"foo":"bar"}}

nestedStruct := (*jsonStruct)["parent_key"]
fmt.Printf("%#v\n", nestedStruct)
// => map[string]interface {}{"foo":"bar"}
// Whilst this shows the runtime knows its actual type is
// map[string]interface, the compiler only knows it to be an interface{}.

// First we assert for the compiler that it is indeed a
// map[string]interface{} we are working with. You can imagine the issues
// that might arrise if we has passed in `{"parent_key": 123}`.
mapConfig, ok := nestedStruct.(map[string]interface{})
if !ok {
// TODO: Error-handling.
}

// Now that the compiler can be sure mapConfig is a map[string]interface{}
// we can type-cast it to GeneralConfig:
config := GeneralConfig(mapConfig)
fmt.Printf("%#v\n", config)
// => main.GeneralConfig{"foo":"bar"}
}

关于解码 json 的 Golang 类型转换/断言问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36874689/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com