28

What are you trying to accomplish?

I am trying to parse data from a json api.

Paste the part of the code that shows the problem.

package main

import (
        "encoding/json"
        "fmt"
        "io/ioutil"
        "net/http"
)

type Structure struct {
        stuff []interface{}
}

func main() {
        url := "https://api.coinmarketcap.com/v1/ticker/?start=0&limit=100"
        response, err := http.Get(url)
        if err != nil {
                panic(err)
        }   
        body, err := ioutil.ReadAll(response.Body)
        if err != nil {
                panic(err)
        }   
        decoded := &Structure{}
        fmt.Println(url)
        err = json.Unmarshal(body, decoded)
        if err != nil {
                panic(err)
        }   
        fmt.Println(decoded)
}

What do you expect the result to be?

I expected for the code to return a list of interface objects.

What is the actual result you get?

I got an error: panic: json: cannot unmarshal array into Go value of type main.Structure

Community
  • 1
  • 1
Peter S
  • 827
  • 1
  • 8
  • 24

4 Answers4

36

The application is unmarshalling a JSON array to a struct. Unmarshal to a slice:

 var data []interface{}
 err = json.Unmarshal(body, &data)

Consider unmarshalling to a slice of structs specific to the response data:

 type Tick struct {
     ID string
     Name string
     Symbol string
     Rank string
     Price_USD string
     ... and so on
}

 var data []Tick
 err = json.Unmarshal(body, &data)
Charlie Tumahai
  • 113,709
  • 12
  • 249
  • 242
  • "cannot unmarshal array into Go value of type main. Structure" Actually the problem is simple, we are trying to parse an array of data with a struct type(object). Even if we try to unmarshal response with a variable of type array of string("[]string") unmarshal will panic. But an array of any struct"[]MyStruct" will parse but give zero value if key doesn't match. – Vaisakh Rajagopal Jul 05 '19 at 09:09
16

i had same problem. use this code:

type coinsData struct {
    Symbol string `json:"symbol"`
    Price  string `json:"price_usd"`
}

func main() {
resp, err := http.Get("https://api.coinmarketcap.com/v1/ticker/?limit=0")
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)

    if err != nil {
        log.Fatal(err)
    }

    var c []coinsData
    err = json.Unmarshal(body, &c)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%v\n", c)
    }

You'll get the result: [{BTC 7986.77} {ETH 455.857} {XRP 0.580848}...]

olekus
  • 161
  • 1
  • 2
1

This code will fetch the value into the Slice. or just update your slice accordingly.

package main

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

type coinsData struct {
    Symbol string `json:"symbol"`
    Price  string `json:"price_usd"`
}

func main() {
    url := "https://api.coinmarketcap.com/v1/ticker/?limit=0"
    res, err := http.Get(url)
    if err != nil {
        fmt.Println(err)
    }
    defer res.Body.Close()
    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Println(err)
    }

    var data []coinsData

    err = json.Unmarshal(body, &data)
    if err != nil {
        panic(err)
    }

    for _, values := range data {
        log.Fatal(fmt.Println(values.Symbol, "\n", values.Price, "\n"))
    }
}
Chikku Jacob
  • 2,114
  • 1
  • 18
  • 33
0

Just a side note, you may also receive this error for simply trying to unintentionally unmarshal an Array as an object that should be an object or possibly vice versa.

Similarly, you may see errors trying to unmarshal a number as a string.

json: cannot unmarshal number into Go struct field blah of type string

Check your input (GIGO).