用go语言解析嵌套的JSON

时间:2017-07-08 16:25:29

标签: go

我如何解析并从JSON下面提取某些值

以下是JSON响应示例

{
   "success":true,
   "endpoint":"https://api.abcxyz.com",
   "info":{
      "Guestconnected":134,
      "Guestratio":100000.06963,
      "symbol1":{
         "code":"NY",
         "symbol":"*",
         "name":"newyear",
         "codev":391.78161,
         "symbolAppearsAfter":false,
         "local":true
      },
      "symbol2":{
         "code":"HNY",
         "symbol":"@",
         "name":"HappyNewYear",
         "codev":1000000.0960,
         "symbolAppearsAfter":true,
         "local":false
      },
      "latest":{
         "value":1597509,
         "autovalue":"00099cf8da58a36c08f2ef98650ff6043ddfb",
         "height":474696,
         "time":1499527696
      }
   },
   "Allguest":{
      "all":4,
      "filtered":4,
      "total_invitations":15430,
      "sent_invitations":15430,
      "final_invitations":0
   },
   "Guestlist":[
      {
         "GuestCode":"369AR",
         "all":2,
         "total_invitations":5430,
         "sent_invitations":5430,
         "final_invitations":0,
         "change":0,
         "accounts":0
      },
      {
         "GuestCode":"6POIA96TY",
         "all":2,
         "total_invitations":10000,
         "sent_invitations":10000,
         "final_invitations":0,
         "change":0,
         "accounts":0
      }
   ]
}

我的代码是:

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
)


type object struct {
    Success bool `json:"success"`
    Endpoint string `json:"endpoint"`
    Allguest struct {
        All int `json:"all"`
        Filtered int `json:"filtered"`
        TotalInvitations int `json:"total_invitations"`
        SentInvitations int `json:"sent_invitations"`
        FinalInvitations int `json:"final_invitations"`
    } `json:"Allguest"`
    Guestlist []struct {
        GuestCode string `json:"GuestCode"`
        All int `json:"all"`
        TotalInvitations int `json:"total_invitations"`
        SentInvitations int `json:"sent_invitations"`
        FinalInvitations int `json:"final_invitations"`
        Change int `json:"change"`
        Accounts int `json:"accounts"`
    } `json:"Guestlist"`
}

func main() {

uri := "https://siteurl.com/api?lists=1"
res, err := http.Get(uri)
fmt.Println(uri)
if err != nil {
fmt.Println("Error:", err)
    log.Fatal(err)
}
defer res.Body.Close()

 var s object
err := json.NewDecoder(res.Body).Decode(&s)
if err != nil {
    log.Fatal(err)
    fmt.Println("Error:", err)
}
fmt.Println(s.Success)
fmt.Println(s.Allguest.TotalInvitations)
for i := 0; i < 6; i++ {
fmt.Println(s.Guestlist[i].TotalInvitations)
)

}

问题是:

  1. 如果回复为空则提供index out of range error我们如何避免这种情况?

  2. 如果TotalInvitations值大于100,则应用条件,然后保存在100.csv其他保存在others.csv

3 个答案:

答案 0 :(得分:1)

如果您只需要JSON中的某些条目,则可以定义仅包含您感兴趣的字段的结构。如果value可以为null,则最好在结构中声明指针。请看一下go playground的一个例子:https://play.golang.org/p/mEwSXvPg3D

答案 1 :(得分:0)

使用gjson pkg以简单的方式从json文档中获取值

示例:

package main

import (
    "fmt"

    "github.com/tidwall/gjson"
)

func main() {
    data := []byte(`{
   "success": true,
   "endpoint": "https://api.abcxyz.com",
   "info": {
      "Guestconnected": 134,
      "Guestratio": 100000.06963,
      "symbol1": {
         "code": "NY",
         "symbol": "*",
         "name": "newyear",
         "codev": 391.78161,
         "symbolAppearsAfter": false,
         "local": true
      },
      "symbol2": {
         "code": "HNY",
         "symbol": "@",
         "name": "HappyNewYear",
         "codev": 1000000.096,
         "symbolAppearsAfter": true,
         "local": false
      },
      "latest": {
         "value": 1597509,
         "autovalue": "00099cf8da58a36c08f2ef98650ff6043ddfb",
         "height": 474696,
         "time": 1499527696
      }
   },
   "Allguest": {
      "all": 4,
      "filtered": 4,
      "total_invitations": 15430,
      "sent_invitations": 15430,
      "final_invitations": 0
   },
   "Guestlist": [
      {
         "GuestCode": "369AR",
         "all": 2,
         "total_invitations": 5430,
         "sent_invitations": 5430,
         "final_invitations": 0,
         "change": 0,
         "accounts": 0
      },
      {
         "GuestCode": "6POIA96TY",
         "all": 2,
         "total_invitations": 10000,
         "sent_invitations": 10000,
         "final_invitations": 0,
         "change": 0,
         "accounts": 0
      }
   ]
    }
    `)

    r := gjson.GetBytes(data, "Allguest.total_invitations")
    fmt.Println(r.Value()) // output 15430

    r = gjson.GetBytes(data, "Guestlist.#.total_invitations")
    fmt.Println(r.Value()) // output [5430 10000]
}

答案 2 :(得分:0)

  1.   

    如果响应为null,则表示索引超出范围错误   我们避免这个?

    除非我误解你,否则回答无效并不重要。如果您收到2个Guestlist项目,则只能循环显示这两个项目,这意味着for i := 0; i < 6; i++是错误的。将其更改为for i := 0; i < len(s.Guestlist); i++for i := range s.Guestlist

  2.   

    如果TotalInvitations值大于100则应用条件   保存在100.csv中保存在others.csv

    您可能希望os包的Create函数创建一个用于写入的新文件或OpenFile函数,O_CREATE, O_WRONLY, and O_APPEND文件打开标志,您可以将0755作为权限模式(或者如果要更改文件的访问权限,则传递另一组八进制权限)。

    然后,您可以使用csvWriter := csv.NewWriter(csvFile)来包装生成的io.Writer(假设打开文件时没有错误)。从那里,您可以将您需要的任何信息作为CSV记录写入文件。不要忘记调用csvWriter.Flush来刷新输出缓冲区,并csvWriter.Error检查是否有错误刷新输出缓冲区。另外,请不要忘记关闭您打开的文件。