我是Go
编程的新手,如果这是显而易见的话,请道歉。我有一个名为JSON
的{{1}}文件:
foo.json
我正在编写一个{"type":"fruit","name":"apple","color":"red"}
程序,当JSON文件中的“name”值为“apple”时,该程序必须执行某些操作。它不需要来自该JSON文件的其他信息,因为该文件在代码的另一个区域中用于完全不同的目的。
我已阅读有关Decode()和Unmarshal()的文档,并附有30个不同的网页,描述如何将整个文件读入结构等等,但这一切似乎都非常复杂,我只想写下正确的代码来实现这个伪代码的前两行:
Go
这样我最终得到一个名为file, _ := os.Open("foo.json")
name = file["name"]
if (name == "apple") {
do stuff
}
的{{1}}变量,其中包含字符串值Go
。在Go中执行此操作的正确方法是什么?
答案 0 :(得分:3)
执行所需操作的最简单方法是解码为结构。
如果格式与{"type":"fruit","name":"apple","color":"red"}
type Name struct {
Name string `json:"name"`
}
var data []byte
data, _ = ioutil.ReadFile("foo.json")
var str Name
_ = json.Unmarshal(data, &str)
if str.Name == "apple" {
// Do Stuff
}
加布斯:
jsonParsed, err := gabs.ParseJSON(data)
name, ok := jsonParsed.Path("name").Data().(string)
杰森:
v, _ := jason.NewObjectFromBytes(data)
name, _ := v.GetString("name")
更新:
结构
type Name struct {
Name string `json:"name"`
}
是json等价于{"name":"foo"}
。
因此,对于具有不同格式的以下json,unmarshaling将不起作用。
[{"name":"foo"}]
{"bar":{"name":"foo"}}
PS:如W.K.S
所述。在您的情况下,匿名结构就足够了,因为您没有将此结构用于其他任何内容。
答案 1 :(得分:2)
有一件事是读取文件而另一件是解码JSON文档。我给你们两个完整的例子。要运行它,您必须在代码或二进制可执行文件的同一目录中有一个名为file.json
的文件:
package main
import (
"encoding/json"
"io/ioutil"
"log"
"os"
)
func main() {
f, err := os.Open("file.json") // file.json has the json content
if err != nil {
log.Fatal(err)
}
bb, err := ioutil.ReadAll(f)
if err != nil {
log.Fatal(err)
}
doc := make(map[string]interface{})
if err := json.Unmarshal(bb, &doc); err != nil {
log.Fatal(err)
}
if name, contains := doc["name"]; contains {
log.Printf("Happy end we have a name: %q\n", name)
} else {
log.Println("Json document doesn't have a name field.")
}
log.Printf("full json: %s", string(bb))
}
答案 2 :(得分:1)
我还尝试在PHP中找到一个简单的解决方案,例如$d = json_decode($json, true)
,并得出结论,在Golang中没有这么简单的方法。以下是我可以制作的最简单的解决方案(为了清楚起见,跳过了检查):
var f interface{}
err = json.Unmarshal(file, &f)
m := f.(map[string]interface{})
if (m["name"] == "apple") {
// Do something
}
,其中
file
是JSON字符串的字节数组,f
接口用作未知JSON结构的通用容器,m
是type assertion返回的地图。我们可以断言f
是一个字符串映射,因为Unmarshal()
为任何JSON输入构建了该类型的变量。至少,我无法让它返回不同的东西。可以通过run-time reflection:
fmt.Printf("Type of f = %s\n", reflect.TypeOf(f))
对于上面的f
变量,代码将打印Type of f = map[string]interface {}
。
这是包含必要检查的完整代码:
package main
import (
"fmt"
"os"
"io/ioutil"
"encoding/json"
)
func main() {
// Read entire file into an array of bytes
file, err := ioutil.ReadFile("foo.json")
if (err != nil) {
fmt.Fprintf(os.Stderr, "Failed read file: %s\n", err)
os.Exit(1)
}
var f interface{}
err = json.Unmarshal(file, &f)
if (err != nil) {
fmt.Fprintf(os.Stderr, "Failed to parse JSON: %s\n", err)
os.Exit(1)
}
// Type-cast `f` to a map by means of type assertion.
m := f.(map[string]interface{})
fmt.Printf("Parsed data: %v\n", m)
// Now we can check if the parsed data contains 'name' key
if (m["name"] == "apple") {
fmt.Print("Apple found\n")
}
}
输出
Parsed data: map[type:fruit name:apple color:red]
Apple found
答案 3 :(得分:1)
正确的Go方法是将解码为只包含所需字段的匿名结构的实例。
func main() {
myStruct := struct{ Name string }{}
json.Unmarshal([]byte(`{"type":"fruit","name":"apple","color":"red"}`), &myStruct)
fmt.Print(myStruct.Name)
}
或者,您可以使用Jeffails/gabs JSON Parser:
jsonParsed,_ := gabs.ParseJSON([]byte(`{"type":"fruit","name":"apple","color":"red"}`));
value, ok = jsonParsed.Path("name").Data().(string)