Parse json data in golang - json

I am trying to print out a json value that I am getting from a public API.
my json response:
[
{
"address": "0x6679eb24f59dfe111864aec72b443d1da666b360",
"name": "ARIVA",
"symbol": "ARV",
"logo": null,
"logo_hash": null,
"thumbnail": null,
"decimals": "8",
"block_number": "8242108",
"validated": 1
}
]
the code:
type TokenNamingInfo struct {
TokenName string `json:"name"`
TokenAddress string `json:"address"`
TokenSymbol string `json:"symbol"`
}
reqmeta, err := http.NewRequest("GET", "https://somesite.com", nil)
if err != nil {
// handle err
}
reqmeta.Header.Set("Accept", "application/json")
reqmeta.Header.Set("X-Api-Key", "api")
respmeta, err := http.DefaultClient.Do(reqmeta)
if err != nil {
// handle err
}
defer respmeta.Body.Close()
var responseTokenSymbol TokenNamingInfo
json.Unmarshal(tokensymbol, &responseTokenPrice)
However, this is not working and does not print.
fmt.Println(responseTokenSymbol.name)
this is working if my json and struct looks like the below, with the same above procedure.
{
"nativePrice": {
"value": "1906303859440",
"decimals": 18,
"name": "Binance Coin",
"symbol": "BNB"
},
"usdPrice": 0.000875604424294528,
"exchangeAddress": "0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73",
"exchangeName": "PancakeSwap v2"
}
type TokenPriceInfo struct {
Price float64 `json:"usdPrice"`
ExchangeName string `json:"exchangeName"`
ExchangeAddress string `json:"exchangeAddress"`
}

You want something like that:
import (
"io/ioutil"
"net/http"
"fmt"
"encoding/json"
)
type TokenNamingInfo struct {
TokenName string `json:"name"`
TokenAddress string `json:"address"`
TokenSymbol string `json:"symbol"`
Logo string `json:"logo"`
LogoHash string `json:"logo_hash"`
Thumbnail string `json:"thumbnail"`
Decimals int `json:"decimals"`
BlockNumber string `json:"block_number"`
Validated string `json:"validated"`
}
reqmeta, err := http.NewRequest("GET", "https://somesite.com", nil)
if err != nil {
// handle err
}
reqmeta.Header.Set("Accept", "application/json")
reqmeta.Header.Set("X-Api-Key", "api")
respmeta, err := http.DefaultClient.Do(reqmeta)
if err != nil {
// handle err
}
defer respmeta.Body.Close()
body, err := ioutil.ReadAll(respmeta.Body)
if err != nil {
// handle err
}
fmt.Println(string(body)) // Print result
responseTokenSymbol := &TokenNamingInfo{}
err = json.Unmarshal(body, responseTokenSymbol)
if err != nil {
// handle error
}
fmt.Println(responseTokenSymbol.TokenName) // Print name

Related

loading static data into nested struct in Go

I am looking to implement something very similar to this GoPlayground example:
https://go.dev/play/p/B4JOVwgdwUk
However my data structure is a bit more complex, with the nested struct called Tag. I can't quite get the syntax correct for how to load the data into the struct in the toFile variable declaration.
Can someone help me figure out what I am doing wrong? I have tried what is displayed in the full code below, as well as this:
Tags: []Tag{
[{"appID:": "go", "category": "backend"},{"appID": "fiber", "category": "framework"}]
}
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
func main() {
type Stack struct {
Reputation int `json:"reputation"`
UserID int `json:"user_id"`
UserType string `json:"user_type"`
ProfileImage string `json:"profile_image"`
DisplayName string `json:"display_name"`
Link string `json:"link"`
Tags []Tag `json:"tags"`
}
type Tag struct {
AppID string `json: "appID:,omitempty"`
Category string `json: "category:,omitempty"`
}
toFile := Stack{
Reputation: 141,
UserID: 9820773,
UserType: "registered",
ProfileImage: "https://graph.facebook.com/10209865263541884/picture?type=large",
DisplayName: "Joe Smith",
Link: "https://stackoverflow.com/users/9820773/joe-smith",
Tags: Tag{
[{"appID:": "go", "category": "backend"},{"appID": "fiber", "category": "framework"}]
} // cannot get this to work
}
// Write it out!
tmpFile, err := ioutil.TempFile(os.TempDir(), "sample-")
if err != nil {
panic(err)
}
defer os.Remove(tmpFile.Name())
err = json.NewEncoder(tmpFile).Encode(toFile)
if err != nil {
panic(err)
}
err = tmpFile.Close()
if err != nil {
panic(err)
}
// Let's read it in!
tmpFile2, err := os.Open(tmpFile.Name())
if err != nil {
panic(err)
}
var fromFile Person
err = json.NewDecoder(tmpFile2).Decode(&fromFile)
if err != nil {
panic(err)
}
err = tmpFile2.Close()
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", fromFile)
}
The comment from #Kousik helped me fix up the code and run it successfully on the GoPlayground:
https://go.dev/play/p/WmZ9m_55W3S
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
func main() {
type Tag struct {
AppID string `json: "appID:,omitempty"`
Category string `json: "category:,omitempty"`
}
type Stack struct {
Reputation int `json:"reputation"`
UserID int `json:"user_id"`
UserType string `json:"user_type"`
ProfileImage string `json:"profile_image"`
DisplayName string `json:"display_name"`
Link string `json:"link"`
Tags []Tag `json:"tags"`
}
toFile := Stack{
Reputation: 141,
UserID: 9820773,
UserType: "registered",
ProfileImage: "https://graph.facebook.com/10209865263541884/picture?type=large",
DisplayName: "Joe Smith",
Link: "https://stackoverflow.com/users/9820773/joe-smith",
Tags: []Tag{{AppID: "id1", Category: "cat1"}, {AppID: "id2", Category: "cat2"}},
}
// Write it out!
tmpFile, err := ioutil.TempFile(os.TempDir(), "sample-")
if err != nil {
panic(err)
}
defer os.Remove(tmpFile.Name())
err = json.NewEncoder(tmpFile).Encode(toFile)
if err != nil {
panic(err)
}
err = tmpFile.Close()
if err != nil {
panic(err)
}
// Let's read it in!
tmpFile2, err := os.Open(tmpFile.Name())
if err != nil {
panic(err)
}
var fromFile Stack
err = json.NewDecoder(tmpFile2).Decode(&fromFile)
if err != nil {
panic(err)
}
err = tmpFile2.Close()
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", fromFile)
}

How do I json unmarshal slice inside a slice

I am trying to unmarshal some pretty ugly json but can't figure out how. I have:
package main
import "fmt"
import "encoding/json"
type PublicKey struct {
ID int `json:"id"`
Key string `json:"key"`
MyData []struct {
ID string `json:"id"`
Value int `json:"value"`
}
}
func main() {
b := `[
{
"id": 1,
"key": "my_key"
},
[
{
"id": "some_id",
"value": 12
},
{
"id": "anorther_id",
"value": 13
}
]
]`
var pk []PublicKey
err := json.Unmarshal([]byte(b), &pk)
if err != nil {
fmt.Println(err)
}
fmt.Println(pk)
}
For the result I am getting:
[{1 my_key []} {0 []}]
The second slice is empty when it shouldn't be.
EDIT:
The error I get is:
json: cannot unmarshal array into Go struct field PublicKey.key of type main.PublicKey
https://play.golang.org/p/cztXOchiiS5
That is some truly hideous JSON! I have two approaches to handling the mixed array elements and I like the 2nd one better. Here's the first approach using interface and a type switch:
package main
import (
"encoding/json"
"errors"
"fmt"
)
type PublicKey struct {
ID int `json:"id"`
Key string `json:"key"`
}
type MyData struct {
ID string `json:"id"`
Value int `json:"value"`
}
type MixedData struct {
Key []PublicKey
MyData [][]MyData
}
func (md *MixedData) UnmarshalJSON(b []byte) error {
md.Key = []PublicKey{}
md.MyData = [][]MyData{}
var obj []interface{}
err := json.Unmarshal([]byte(b), &obj)
if err != nil {
return err
}
for _, o := range obj {
switch o.(type) {
case map[string]interface{}:
m := o.(map[string]interface{})
id, ok := m["id"].(float64)
if !ok {
return errors.New("public key id must be an int")
}
pk := PublicKey{}
pk.ID = int(id)
pk.Key, ok = m["key"].(string)
if !ok {
return errors.New("public key key must be a string")
}
md.Key = append(md.Key, pk)
case []interface{}:
a := o.([]interface{})
myData := make([]MyData, len(a))
for i, x := range a {
m, ok := x.(map[string]interface{})
if !ok {
return errors.New("data array contains unexpected object")
}
val, ok := m["value"].(float64)
if !ok {
return errors.New("data value must be an int")
}
myData[i].Value = int(val)
myData[i].ID, ok = m["id"].(string)
if !ok {
return errors.New("data id must be a string")
}
md.MyData = append(md.MyData, myData)
}
default:
// got something unexpected, handle somehow
}
}
return nil
}
func main() {
b := `[
{
"id": 1,
"key": "my_key"
},
[
{
"id": "some_id",
"value": 12
},
{
"id": "another_id",
"value": 13
}
]
]`
m := MixedData{}
err := json.Unmarshal([]byte(b), &m)
if err != nil {
fmt.Println(err)
}
fmt.Println(m)
}
https://play.golang.org/p/g8d_AsH-pYY
Hopefully there aren't any unexpected other elements, but they can be handled similarly.
Here is the second that relies more on Go's internal JSON parsing with the help of json.RawMessage. It makes the same assumptions about the contents of the array. It assumes that any objects will Unmarshal into PublicKey instances and any arrays consist of only MyData instances. I also added how to marshal back into the target JSON for symmetry:
package main
import (
"encoding/json"
"fmt"
"os"
)
type PublicKey struct {
ID int `json:"id"`
Key string `json:"key"`
}
type MyData struct {
ID string `json:"id"`
Value int `json:"value"`
}
type MixedData struct {
Keys []PublicKey
MyData [][]MyData
}
func (md *MixedData) UnmarshalJSON(b []byte) error {
md.Keys = []PublicKey{}
md.MyData = [][]MyData{}
obj := []json.RawMessage{}
err := json.Unmarshal([]byte(b), &obj)
if err != nil {
return err
}
for _, o := range obj {
switch o[0] {
case '{':
pk := PublicKey{}
err := json.Unmarshal(o, &pk)
if err != nil {
return err
}
md.Keys = append(md.Keys, pk)
case '[':
myData := []MyData{}
err := json.Unmarshal(o, &myData)
if err != nil {
return err
}
md.MyData = append(md.MyData, myData)
default:
// got something unexpected, handle somehow
}
}
return nil
}
func (md *MixedData) MarshalJSON() ([]byte, error) {
out := make([]interface{}, len(md.Keys)+len(md.MyData))
i := 0
for _, x := range md.Keys {
out[i] = x
i++
}
for _, x := range md.MyData {
out[i] = x
i++
}
return json.Marshal(out)
}
func main() {
b := `[
{
"id": 1,
"key": "my_key"
},
[
{
"id": "some_id",
"value": 12
},
{
"id": "another_id",
"value": 13
}
]
]`
m := MixedData{}
err := json.Unmarshal([]byte(b), &m)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(m)
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
if err := enc.Encode(m); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
https://play.golang.org/p/ryZzaWKNcN0
Here's an approach that combines json.RawMessage with the trick of using the default unmarshaler in a type that implements json.Unmarshaler by creating a new temporary type that aliases the target type.
The idea is that we unmarshal the incoming array into a raw message and ensure that the array length is what we expect. Then we unmarshal the individual array elements into the custom struct types using their JSON tag annotations. The end result is that we can unmarshal the PublicKey type in the usual way and the UnmarshalJSON code is not terribly difficult to follow once you understand the tricks.
For example (Go Playground):
type PublicKey struct {
ID int `json:"id"`
Key string `json:"key"`
Data []MyData
}
type MyData struct {
ID string `json:"id"`
Value int `json:"value"`
}
func (pk *PublicKey) UnmarshalJSON(bs []byte) error {
// Unmarshal into a RawMessage so we can inspect the array length.
var rawMessage []json.RawMessage
err := json.Unmarshal(bs, &rawMessage)
if err != nil {
return err
}
if len(rawMessage) != 2 {
return fmt.Errorf("expected array of length 2, got %d", len(rawMessage))
}
// Parse the first object as PublicKey using the default unmarshaler
// using a temporary type that is an alias for the target type.
type PublicKey2 PublicKey
var pk2 PublicKey2
err = json.Unmarshal(rawMessage[0], &pk2)
if err != nil {
return err
}
// Parse the second object as []MyData in the usual way.
err = json.Unmarshal(rawMessage[1], &pk2.Data)
if err != nil {
return err
}
// Finally, assign the aliased object to the target object.
*pk = PublicKey(pk2)
return nil
}
func main() {
var pk PublicKey
err := json.Unmarshal([]byte(jsonstr), &pk)
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", pk)
// main.PublicKey{ID:1, Key:"my_key", Data:[]main.MyData{main.MyData{ID:"some_id", Value:12}, main.MyData{ID:"anorther_id", Value:13}}}
}

How to Unmarshal an inconsistent JSON field that can be a string *or* an array of string?

I am having trouble Unmarshalling some Json I don't have control over.
There is one field that 99% of the time is a string but occasionally is an array.
type MyListItem struct {
Date string `json:"date"`
DisplayName string `json:"display_name"`
}
type MyListings struct {
CLItems []MyListItem `json:"myitems"`
}
var mylist MyListings
err = json.Unmarshal(jsn, &mylist)
if err != nil {
fmt.Print("JSON:\n%s\n error:%v\n", string(jsn),err)
return
}
Json is as follows:
{
"date": "30 Apr",
"display_name": "Mr Smith"
},
{
"date": "30 Apr",
"display_name": ["Mr Smith", "Mr Jones"],
}
error: json: cannot unmarshal array into Go struct field MyListItem.display_name of type string
Use json.RawMessage to capture the varying field.
Use the json "-" name to hide the DisplayName field from decoder. The application will fill this field after the top-level JSON is decoded.
type MyListItem struct {
Date string `json:"date"`
RawDisplayName json.RawMessage `json:"display_name"`
DisplayName []string `json:"-"`
}
Unmarshal the top-level JSON:
var li MyListItem
if err := json.Unmarshal(data, &li); err != nil {
// handle error
}
Unmarshal the display name depending on the type of the raw data:
if len(li.RawDisplayName) > 0 {
switch li.RawDisplayName[0] {
case '"':
if err := json.Unmarshal(li.RawDisplayName, &li.DisplayName); err != nil {
// handle error
}
case '[':
var s []string
if err := json.Unmarshal(li.RawDisplayName, &s); err != nil {
// handle error
}
// Join arrays with "&" per OP's comment on the question.
li.DisplayName = strings.Join(s, "&")
}
}
playground example
Incorporate the above into a for loop to handle MyListings:
var listings MyListings
if err := json.Unmarshal([]byte(data), &listings); err != nil {
// handle error
}
for i := range listings.CLItems {
li := &listings.CLItems[i]
if len(li.RawDisplayName) > 0 {
switch li.RawDisplayName[0] {
case '"':
if err := json.Unmarshal(li.RawDisplayName, &li.DisplayName); err != nil {
// handle error
}
case '[':
var s []string
if err := json.Unmarshal(li.RawDisplayName, &s); err != nil {
// handle error
}
li.DisplayName = strings.Join(s, "&")
}
}
}
playground example
If there's more than one place in the data model where a value can be a string or []string, it can be helpful to encapsulate the logic in a type. Parse the JSON data in an implementation of the json.Unmarshaler interface.
type multiString string
func (ms *multiString) UnmarshalJSON(data []byte) error {
if len(data) > 0 {
switch data[0] {
case '"':
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*ms = multiString(s)
case '[':
var s []string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*ms = multiString(strings.Join(s, "&"))
}
}
return nil
}
Use it like this:
type MyListItem struct {
Date string `json:"date"`
DisplayName multiString `json:"display_name"`
}
type MyListings struct {
CLItems []MyListItem `json:"myitems"`
}
var listings MyListings
if err := json.Unmarshal([]byte(data), &listings); err != nil {
log.Fatal(err)
}
Playground Example
Here's the code to get the value as a slice of strings instead of as a single string with values joined by &.
type multiString []string
func (ms *multiString) UnmarshalJSON(data []byte) error {
if len(data) > 0 {
switch data[0] {
case '"':
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*ms = multiString{s}
case '[':
if err := json.Unmarshal(data, (*[]string)(ms)); err != nil {
return err
}
}
}
return nil
}
Playground example.
As an alternative, this builds off of the answer from #ThunderCat but instead of using json.RawMessage, uses interface{} and a type switch:
package main
import (
"encoding/json"
"fmt"
"log"
)
type MyListItem struct {
Date string `json:"date"`
DisplayName string `json:"-"`
RawDisplayName interface{} `json:"display_name"`
}
func (li *MyListItem) UnmarshalJSON(data []byte) error {
type localItem MyListItem
var loc localItem
if err := json.Unmarshal(data, &loc); err != nil {
return err
}
*li = MyListItem(loc)
switch li.RawDisplayName.(type) {
case string:
li.DisplayName = li.RawDisplayName.(string)
case []interface{}:
vals := li.RawDisplayName.([]interface{})
if len(vals) > 0 {
li.DisplayName, _ = vals[0].(string)
for _, v := range vals[1:] {
li.DisplayName += "&" + v.(string)
}
}
}
return nil
}
func test(data string) {
var li MyListItem
if err := json.Unmarshal([]byte(data), &li); err != nil {
log.Fatal(err)
}
fmt.Println(li.DisplayName)
}
func main() {
test(`
{
"date": "30 Apr",
"display_name": "Mr Smith"
}`)
test(`
{
"date": "30 Apr",
"display_name": ["Mr Smith", "Mr Jones"]
}`)
}
playground

got an error when i tried to call the value with go lang

I just starting learn this Go Lang programming, and now i'm stuck with the [] things, I tried to create a blog using the Go Lang and i'm using a template, there's no problem with the template, it just I want to append a data that I got from json file.
If I just take the data and send it through the file it's already done, but the problem is when I tried to append the slug to the data (because the json file i got no slug url in it.
That's why I want to get the title of the post then make a slug with it, then
package main
import (
"encoding/json"
"fmt"
"github.com/gosimple/slug"
"html/template"
"io/ioutil"
"net/http"
"os"
)
type Blog struct {
Title string
Author string
Header string
}
type Posts struct {
Posts []Post `json:"posts"`
}
type Post struct {
Title string `json:"title"`
Author string `json:"author"`
Content string `json:"content"`
PublishDate string `json:"publishdate"`
Image string `json:"image"`
}
type BlogViewModel struct {
Blog Blog
Posts []Post
}
func loadFile(fileName string) (string, error) {
bytes, err := ioutil.ReadFile(fileName)
if err != nil {
return "", err
}
return string(bytes), nil
}
func loadPosts() []Post {
jsonFile, err := os.Open("source/posts.json")
if err != nil {
fmt.Println(err)
}
fmt.Println("Successfully open the json file")
defer jsonFile.Close()
bytes, _ := ioutil.ReadAll(jsonFile)
var post []Post
json.Unmarshal(bytes, &post)
return post
}
func handler(w http.ResponseWriter, r *http.Request) {
blog := Blog{Title: "asd", Author: "qwe", Header: "zxc"}
posts := loadPosts()
viewModel := BlogViewModel{Blog: blog, Posts: posts}
t, _ := template.ParseFiles("template/blog.html")
t.Execute(w, viewModel)
}
The error is show in the main function
func main() {
posts := loadPosts()
for i := 0; i < len(posts.Post); i++ { // it gives me this error posts.Post undefined (type []Post has no field or method Post)
fmt.Println("Title: " + posts.Post[i].Title)
}
// http.HandleFunc("/", handler)
// fs := http.FileServer(http.Dir("template"))
// http.Handle("/assets/css/", fs)
// http.Handle("/assets/js/", fs)
// http.Handle("/assets/fonts/", fs)
// http.Handle("/assets/images/", fs)
// http.Handle("/assets/media/", fs)
// fmt.Println(http.ListenAndServe(":9000", nil))
}
I already try to solved it a couple of hours but I hit the wall, I think it's possible but I just don't find the way, I don't know what is the good keyword to solve the problem.
And I don't if I already explain good enough or not. Please help me, thank you
This is the JSON file format
{
"posts": [
{
"title": "sapien ut nunc",
"author": "Jeni",
"content": "jgwilt0#mapquest.com",
"publishdate": "26.04.2017",
"image": "http://dummyimage.com/188x199.png/cc0000/ffffff"
},
{
"title": "mus vivamus vestibulum sagittis",
"author": "Analise",
"content": "adonnellan1#biblegateway.com",
"publishdate": "13.03.2017",
"image": "http://dummyimage.com/182x113.bmp/ff4444/ffffff"
}
]
}
You're loadPost method returns []Post. Your definition of Post does not contain the attribute Post. Your Posts struct does.
Here is a modified working example. I didn't define your other structures for brevity.
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
)
var rawJson = `{
"posts": [
{
"title": "sapien ut nunc",
"author": "Jeni",
"content": "jgwilt0#mapquest.com",
"publishdate": "26.04.2017",
"image": "http://dummyimage.com/188x199.png/cc0000/ffffff"
},
{
"title": "mus vivamus vestibulum sagittis",
"author": "Analise",
"content": "adonnellan1#biblegateway.com",
"publishdate": "13.03.2017",
"image": "http://dummyimage.com/182x113.bmp/ff4444/ffffff"
}
]
}`
type Data struct {
Posts []struct {
Title string `json:"title"`
Author string `json:"author"`
Content string `json:"content"`
Publishdate string `json:"publishdate"`
Image string `json:"image"`
} `json:"posts"`
}
func loadFile(fileName string) (string, error) {
bytes, err := ioutil.ReadFile(fileName)
if err != nil {
return "", err
}
return string(bytes), nil
}
func loadData() (Data, error) {
var d Data
// this is commented out so that i can load raw bytes as an example
/*
f, err := os.Open("source/posts.json")
if err != nil {
return d, err
}
defer f.Close()
bytes, _ := ioutil.ReadAll(f)
*/
// replace rawJson with bytes in prod
json.Unmarshal([]byte(rawJson), &d)
return d, nil
}
func main() {
data, err := loadData()
if err != nil {
log.Fatal(err)
}
for i := 0; i < len(data.Posts); i++ {
fmt.Println("Title: " + data.Posts[i].Title)
}
/*
// you can also range over the data.Posts if you are not modifying the data then using the index is not necessary.
for _, post := range data.Posts {
fmt.Println("Title: " + post.Title)
}
*/
}
modified just for files
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
)
type Data struct {
Posts []struct {
Title string `json:"title"`
Author string `json:"author"`
Content string `json:"content"`
Publishdate string `json:"publishdate"`
Image string `json:"image"`
} `json:"posts"`
}
func loadData() (Data, error) {
var d Data
b, err := ioutil.ReadFile("source/posts.json")
if err != nil {
return d, err
}
err = json.Unmarshal(b, &d)
if err != nil {
return d, err
}
return d, nil
}
func main() {
data, err := loadData()
if err != nil {
log.Fatal(err)
}
for _, post := range data.Posts {
fmt.Println("Title: " + post.Title)
}
}

How do I decode the following JSON?

I have a JSON object of the format
{
"results": [
{
"hits": [
{
"title": "Juliette DELAUNAY",
"author:url": "abc.com"
}
]
}
]
}
To decode in my go program, I have made the following structs
type results struct{
Result []result `json:"results"`
}
type result struct{
Hits []hit `json:"hits"`
}
type hit struct{
Name string `json:"title"`
Url string `json:"author:url"`
}
var m =make(map[string]string)
var t results
But when I try to do the following,
decoder := json.NewDecoder(resp.Body)
err = decoder.Decode(&t)
if err != nil {
fmt.Println(err)
}
for _,x := range t.Result[0].Hits{
m[x.Name] = x.Url
fmt.Println(x.Name,x.Url)
}
It gives a runtime error saying index is out of range. What am I doing wrong? Are my structs incorrect for the given json?
EDIT : The JSON file I need to decode
var jsonStr = []byte(`{"requests":[{"indexName":"recherchepepitesAtoZ","params":"query=x&hitsPerPage=2817&maxValuesPerFacet=42&page=0&facets=%5B%22field_frenchtech_hub_pepite%22%2C%22field_categorie%22%2C%22field_frenchtech_hub_pepite%22%5D&tagFilters="}]}`)
req, err := http.NewRequest("POST", "http://6y0slgl8yj-dsn.algolia.net/1/indexes/*/queries?x-algolia-agent=Algolia%20for%20vanilla%20JavaScript%20(lite)%203.20.4%3Binstantsearch.js%201.10.4%3BJS%20Helper%202.18.0&x-algolia-application-id=6Y0SLGL8YJ&x-algolia-api-key=6832a361e1e1628f8ddb2483623104c6", bytes.NewBuffer(jsonStr))
//req.Header.Set("X-Custom-Header", "application/x-www-form-urlencoded")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
Here is a slightly modified version that works on my machine and go playground:
GoPlayground
package main
import (
"encoding/json"
"fmt"
"strings"
)
type results struct {
Result []result `json:"results"`
}
type result struct {
Hits []hit `json:"hits"`
}
type hit struct {
Name string `json:"title"`
Url string `json:"author:url"`
}
var m = make(map[string]string)
func main() {
jsonSample := `{
"results": [
{
"hits": [
{
"title": "Juliette DELAUNAY",
"author:url": "abc.com"
}
]
}
]
}`
var t results
decoder := json.NewDecoder(strings.NewReader(jsonSample))
err := decoder.Decode(&t)
if err != nil {
fmt.Println(err)
}
for _, x := range t.Result[0].Hits {
m[x.Name] = x.Url
fmt.Println(x.Name, x.Url)
}
}