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

时间:2016-12-23 03:04:47

标签: json go

我是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中执行此操作的正确方法是什么?

4 个答案:

答案 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
}

您的其他选择是使用第三方库,例如gabsjason

加布斯:

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))
}

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

答案 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结构的通用容器,
  • mtype 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)
}

Playground Link

或者,您可以使用Jeffails/gabs JSON Parser:

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