1

I want to parse the following JSON output:

{
    "total":5689,
    "result":{
        "6581":{
            "percent":37.79,
            "count":2150
        },
        "6591":{
            "percent":35.31,
            "count":2009
        },
        "6601":{
            "percent":26.89,
            "count":1530
        }
    }
}

I have read that JSON can be parsed into a struct if the format is known:

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

type VoteResult struct {
    Total  int `json:"total"`
    Result struct {
        Efid1 struct {
            Percent float64 `json:"percent"`
            Count   int     `json:"count"`
        }
        Efid2 struct {
            Percent float64 `json:"percent"`
            Count   int     `json:"count"`
        }
        Efid3 struct {
            Percent float64 `json:"percent"`
            Count   int     `json:"count"`
        }
    }
}

func main() {
    b := []byte(`{"total":5689,"result":{"6581":{"percent":37.79,"count":2150}
    ,"6591":{"percent":35.31,"count":2009},"6601":{"percent":26.89,"count":1530}}}`)

    var v VoteResult

    err := json.Unmarshal(b, &v)
    if err != nil {
        fmt.Fprintf(os.Stderr, "%v\n", err)
        os.Exit(1)
    }

    fmt.Println(v)
}

Go Playground

This is the output, but something is wrong as the nested structs are not filled with data:

{5689 {{0 0} {0 0} {0 0}}}

What am I doing wrong?

1 Answer 1

1

The result part of the JSON is a dictionary mapping strings to objects. Try this instead (https://play.golang.org/p/BCNHw-OH2I):

type VoteResult struct {
    Total  int `json:"total"`
    Result map[string]struct {
        Percent float64 `json:"percent"`
        Count   int     `json:"count"`
    }
}

EDIT

As an alternative, if those strings are truly fixed, you could do this:

type VoteResult struct {
    Total  int `json:"total"`
    Result struct {
        Efid1 struct {
            Percent float64 `json:"percent"`
            Count   int     `json:"count"`
        } `json:"6581"`
        Efid2 struct {
            Percent float64 `json:"percent"`
            Count   int     `json:"count"`
        } `json:"6591"`
        Efid3 struct {
            Percent float64 `json:"percent"`
            Count   int     `json:"count"`
        } `json:"6601"`
    }
}

Here we've just decided that Efid1 has the JSON key 6591, etc. But I suspect a map of strings to structs is a better fit for the data structure you have.

Sign up to request clarification or add additional context in comments.

6 Comments

He's just missing a tag. Changing his data type to something dynamic isn't a good solution to that problem.
@evanmcdonnal I'm not sure what makes you think that. The default JSON tag for Result is result already. Adding a tag shouldn't (and doesn't when I just tried it) make a difference.
yeah you're right, that works fine and my code was wrong, didn't read the post closely enough. Result needs to be a dictionary because the objects have keys. He could do something like what I have but it doesn't really make sense imo (the three inner structs would also need tags and I bet their names change from one response to another).
@evanmcdonnal Yeah, I added an alternative that shows that approach, but as you said, it's probably not the right thing.
Thanks. I could not figure out where the tags for the inner structs should go, I put them after struct but that did not work. However, I like the first example much better as this is more compact and will also work when name of inner structs change.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.