如何在golang中将json文件读取为json对象

41

我有一个JSON文件存储在本地机器上。我需要将其读入变量并循环遍历以获取JSON对象的值。如果我使用ioutil.Readfile方法读取文件后使用Marshal命令,则会输出一些数字。以下是我的几次尝试:

尝试1:

plan, _ := ioutil.ReadFile(filename) // filename is the JSON file to read
var data interface{}
err := json.Unmarshal(plan, data)
if err != nil {
        log.Error("Cannot unmarshal the json ", err)
      }
fmt.Println(data)

它给我以下错误提示:

time="2016-12-13T22:13:05-08:00" level=error msg="Cannot unmarshal the json json: Unmarshal(nil)"
<nil>
尝试2:我尝试将JSON值存储在结构中,然后使用MarshalIndent。
generatePlan, _ := json.MarshalIndent(plan, "", " ") // plan is a pointer to a struct
fmt.Println(string(generatePlan))

它以字符串形式输出。但是如果我将输出强制转换为字符串,则无法将其作为JSON对象循环。

在golang中,我们如何将JSON文件读取为JSON对象?是否可能做到这一点?非常感谢您的帮助!

2个回答

66
json.Unmarshal需要填充的值必须是指针。
来自GoDoc

Unmarshal解析JSON编码的数据并将结果存储在由v指向的值指针中。

所以你需要做以下操作:
plan, _ := ioutil.ReadFile(filename)
var data interface{}
err := json.Unmarshal(plan, &data)

您的错误(Unmarshal(nil))表明读取文件时出现了问题,请检查ioutil.ReadFile返回的错误信息。


此外,请注意在使用空接口进行解组(unmarshal)时,您需要使用类型断言(type assertion)将底层值转换为Go基本类型。

为了将JSON解组(unmarshal)为接口值,Unmarshal将以下内容之一存储在接口值中:

bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null
使用具体的结构通过 Unmarshal 来填充你的 JSON 是一种更好的方法。

11
如果您正在2022年查看此内容,ioutil包已被弃用。虽然您仍然可以使用它,但会收到烦人的错误信息。
相反,您可以使用os包。
someStruct := SomeStruct{}  // Read errors caught by unmarshal
fileBytes, _ := os.ReadFile(filename)   
err := json.Unmarshal(fileBytes, spec) 

注意,我特意忽略了来自os.ReadFile的错误,因为这也会导致示例中json.Unmarshal发生错误。

谢谢您的更新和澄清!我从Python转到golang,正准备深入研究os和ioutil包之间的区别。 - user2662241
非常好的回答。我只是想知道 err := json.Unmarshal(fileBytes, spec) 中的 spec 是什么意思?抱歉,我是 GoLang 的新手,正在逐渐熟悉这门语言。 - Jason
@Jason 根据我从源材料和其他评论中了解到的情况,这应该是你将 JSON 反序列化为的结构体。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接