代码之家  ›  专栏  ›  技术社区  ›  Ed Morton

如何使用Go从JSON文件读取一个值

  •  1
  • Ed Morton  · 技术社区  · 8 年前

    我是编程新手 Go 所以,如果这是显而易见的,请道歉。我有一个 JSON 文件名 foo.json :

    {"type":"fruit","name":"apple","color":"red"}
    

    我正在写一篇 当JSON文件中的“name”值为“apple”时,必须执行某些操作的程序。它不需要来自JSON文件的其他信息,因为该文件在代码的另一个区域用于完全不同的目的。

    我已经阅读了关于Decode()和Unmarshal()的文档,并使用了大约30个不同的网页来描述如何将整个文件读入结构等。但对于我想做的事情来说,这一切似乎都非常复杂,只需要编写正确的代码来实现这个伪代码的前2行:

    file, _ := os.Open("foo.json")
    name = file["name"]
    if (name == "apple") {
        do stuff
    }
    

    因此,我最终得到了一个 变量名 name 包含字符串值的 apple .在Go中这样做的正确方法是什么?

    4 回复  |  直到 8 年前
        1
  •  4
  •   John S Perayil    8 年前

    最简单的方法是将其解码为结构。

    只要格式保持类似: {"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
    }
    

    另一种选择是使用第三方库,例如 gabs jason .

    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,解组将不起作用。

    [{"name":"foo"}]
    
    {"bar":{"name":"foo"}}
    

    PS:如所述 W.K.S 在您的情况下,匿名结构就足够了,因为您没有将此结构用于任何其他用途。

        2
  •  4
  •   Yandry Pozo    6 年前

    一个是读取文件,另一个是解码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))
    }
    

    https://play.golang.org/p/0u04MwwGfn

        3
  •  1
  •   Ruslan Osmanov    8 年前

    我还试图找到一个简单的解决方案,例如: $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
    
        4
  •  1
  •   W.K.S    8 年前

    正确的方法是将其解码为只包含所需字段的匿名结构的实例。

    func main() {
        myStruct := struct{ Name string }{}
        json.Unmarshal([]byte(`{"type":"fruit","name":"apple","color":"red"}`), &myStruct)
        fmt.Print(myStruct.Name)
    }
    

    Playground Link

    或者,您可以使用 Jeffails/gabs JSON解析器:

    jsonParsed,_ := gabs.ParseJSON([]byte(`{"type":"fruit","name":"apple","color":"red"}`));
    value, ok = jsonParsed.Path("name").Data().(string)