douhuijun3776
2016-12-23 03:04
浏览 507

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

I an new to programming in Go so apologies if this is something obvious. I have a JSON file named foo.json:

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

and I am writing a Go program that has to do something when the "name" value in the JSON file is "apple". It needs no other information from that JSON file as that file is used for a completely different purpose in another area of the code.

I have read documentation on Decode() and Unmarshal() and abut 30 different web pages describing how to read the whole file into structures, etc. but it all seems extremely complicated for what I want to do which is just write the correct code to implement the first 2 lines of this pseudo-code:

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

such that I end up with a Go variable named name that contains the string value apple. What is the right way to do this in Go?

图片转代码服务由CSDN问答提供 功能建议

Go 中编程的新手,如果这很明显,我们深表歉意。 我有一个名为 foo.json JSON 文件:

  {“ type”:“ fruit”,“ name”  :“ apple”,“ color”:“ red”} 
   
 
 

,而我正在编写一个 Go 程序,该程序必须在 JSON文件中的“名称”值是“苹果”。 它不需要来自该JSON文件的其他信息,因为该文件在代码的另一个区域用于完全不同的用途。

我已阅读了Decode()和Unmarshal()的文档, 紧靠30个不同的网页,它们描述了如何将整个文件读入结构等,但是对于我想做的事情来说,这似乎非常复杂,只需编写正确的代码以实现此伪代码的前两行即可:

  file,_:= os.Open(“ foo.json”)
name = file [“ name”] 
if(name ==“ apple”){
做 东西
} 
   
 
 

这样我最终得到一个名为 name Go 变量,该变量包含字符串 值 apple 。 在Go中执行此操作的正确方法是什么?

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

4条回答 默认 最新

  • doz97171 2016-12-23 06:09
    已采纳

    The easiest method to do what you want is to decode into a struct.

    Provided the format remains similar to {"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
    }
    

    Your other option is to use third party libraries such as gabs or jason.

    Gabs :

    jsonParsed, err := gabs.ParseJSON(data)
    name, ok := jsonParsed.Path("name").Data().(string)
    

    Jason :

    v, _ := jason.NewObjectFromBytes(data)
    name, _ := v.GetString("name")
    

    Update :

    The structure

    type Name struct {
        Name string `json:"name"`
    }
    

    is the json equivalent of {"name":"foo"}.

    So unmarshaling won't work for the following json with different formats.

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

    PS : As mentioned by W.K.S. In your case an anonymous struct would suffice since you're not using this structure for anything else.

    打赏 评论
  • dswqw66280 2016-12-23 03:36

    One thing is reading a file and other one is decoding a JSON document. I leave you a full example doing both. To run it you have to have a file called file.json in the same directory of your code or binary executable:

    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
    ", 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

    打赏 评论
  • dqab0824 2016-12-23 05:20

    I have also tried to find a simple solution such as $d = json_decode($json, true) in PHP and came to the conclusion that there is no such simple way in Golang. The following is the simplest solution I could make (the checks are skipped for clarity):

    var f interface{}
    err = json.Unmarshal(file, &f)
    
    m := f.(map[string]interface{})
    if (m["name"] == "apple") {
      // Do something
    }
    

    where

    • file is an array of bytes of JSON string,
    • f interface serves as a generic container for unknown JSON structure,
    • m is a map returned by the type assertion.

    We can assert that f is a map of strings, because Unmarshal() builds a variable of that type for any JSON input. At least, I couldn't make it return something different. It is possible to detect the type of a variable by means of run-time reflection:

    fmt.Printf("Type of f = %s
    ", reflect.TypeOf(f))
    

    For the f variable above, the code will print Type of f = map[string]interface {}.

    Example

    And this is the full code with necessary checks:

    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
    ", err)
        os.Exit(1)
      }
    
      var f interface{}
      err = json.Unmarshal(file, &f)
      if (err != nil) {
        fmt.Fprintf(os.Stderr, "Failed to parse JSON: %s
    ", 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
    ", m)
    
      // Now we can check if the parsed data contains 'name' key
      if (m["name"] == "apple") {
        fmt.Print("Apple found
    ")
      }
    }
    

    Output

    Parsed data: map[type:fruit name:apple color:red]
    Apple found
    
    打赏 评论
  • dongshai1944 2016-12-23 06:24

    The proper Go way of doing this would be to decode into an instance of an anonymous struct containing only the field you need.

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

    Playground Link

    Alternatively, You could use Jeffails/gabs JSON Parser:

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

相关推荐 更多相似问题