英文:
Parsing nested JSON in go language
问题
如何解析和提取以下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)
}
}
问题是:
-
如果响应为空,它会给出“索引超出范围错误”,我们如何避免这种情况?
-
如果
TotalInvitations
的值大于100
,则将其保存在100.csv
中,否则保存在others.csv
中。
英文:
How could I parse and extract certain values from below JSON
Here is the sample JSON response
{
"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
}
]
}
My Code is :
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)
)
}
The problem is :
-
If the response is null it is giving
index out of range error
how can we avoid this ? -
Applying condition if
TotalInvitations
value is greater than100
then save in100.csv
else save inothers.csv
答案1
得分: 1
如果您只需要从JSON中获取特定的条目,您可以定义一个只包含您感兴趣的字段的结构。如果值可以为null,最好在结构中声明一个指针。请查看Go Playground上的示例:https://play.golang.org/p/mEwSXvPg3D
英文:
If you need only certain entries from JSON you can define a structure with only those fields you are interested in. And if value can be null it is better to declare a pointer in the structure. Please take a look at an example at go playground: https://play.golang.org/p/mEwSXvPg3D
答案2
得分: 0
使用gjson包以简单的方式从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()) // 输出 15430
r = gjson.GetBytes(data, "Guestlist.#.total_invitations")
fmt.Println(r.Value()) // 输出 [5430 10000]
}
英文:
use gjson pkg to get value from json document an simple way
example:
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]
}
答案3
得分: 0
> 如果响应为null,则会出现索引超出范围的错误,我们如何避免这种情况?
除非我误解了你的意思,响应为null不应该有影响。如果你收到了2个Guestlist项,你只能循环遍历这2个项,意味着for i := 0; i < 6; i++
是错误的。将其改为for i := 0; i < len(s.Guestlist); i++
或for i := range s.Guestlist
。
> 如果TotalInvitations的值大于100,则保存在100.csv中,否则保存在others.csv中。
你可能需要使用os
包的Create
函数来创建一个新的文件用于写入,或者使用OpenFile
函数、O_CREATE
、O_WRONLY
和O_APPEND
文件打开标志,并且可以将0755
作为权限模式(或者如果你想更改文件的访问权限,可以使用其他一组八进制权限)。
然后,你可以使用csvWriter := csv.NewWriter(csvFile)
来包装生成的io.Writer
(假设打开文件时没有错误)。然后,你可以将所需的任何信息以CSV记录的形式写入文件。不要忘记调用csvWriter.Flush
来刷新输出缓冲区,以及使用csvWriter.Error
来检查是否在刷新输出缓冲区时出现错误。还要记得关闭你打开的文件。
英文:
> If the response is null it is giving index out of range error how can
> we avoid this?
Unless I'm misunderstanding you, the response being null shouldn't matter. If you receive 2 Guestlist items, you can only loop over those 2, meaning `for i := 0; i < 6; i++` is wrong. Change it to `for i := 0; i < len(s.Guestlist); i++` or `for i := range s.Guestlist`.
> Applying condition if TotalInvitations value is greater than 100 then
> save in 100.csv else save in others.csv
You will probably want the `os` package's [`Create`](https://golang.org/pkg/os/#Create) function to create a new file for writing or the [`OpenFile`](https://golang.org/pkg/os/#OpenFile) function, the [`O_CREATE`, `O_WRONLY`, and `O_APPEND`](https://golang.org/pkg/os/#O_WRONLY) file-open flags, and you can pass `0755` as the permission mode (or another set of octal permissions if you want to change access of a file).
You can then use `csvWriter := csv.NewWriter(csvFile)` to wrap the resulting `io.Writer` (assuming there is no error opening the file). From there, you can just write whatever information you require to the file as CSV records. Don't forget to call `csvWriter.Flush` to flush the output buffer and `csvWriter.Error` to check whether there was an error flushing the output buffer. Also don't forget to close the file you opened.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论