1

I am trying to parse a nested json string

I did get it to work by using multiple structs, but I am wondering if I can parse the JSON without using an extra struct.

type Events struct {
    Events []Event `json:"events"`
}

type Event struct {
    Name    string  `json:"name"`
    Url     string  `json:"url"`
    Dates   struct {
        Start   struct {
            LocalDate   string 
            LocalTime   string
        }
    }
}

type Embed struct {
    TM Events `json:"_embedded"`
}

func TMGetEventsByCategory(location string, category string) {
    parameters := "city=" + location + "&classificationName=" + category + "&apikey=" + api_key
    tmUrl := tmBaseUrl + parameters
    resp, err := http.Get(tmUrl)
    var embed Embed
    var tm Event
    if err != nil {
        log.Printf("The HTTP request failed with error %s\n", err)
    } else {
        data, _ := ioutil.ReadAll(resp.Body)

        err := json.Unmarshal(data, &embed)
        json.Unmarshal(data, &tm)

    }
}

JSON Data looks like this:

{
  "_embedded": { 
     "events": [],
  },
  "OtherStuff": {
  }
}

Is it possible to get rid of the Embed struct and read straight to the events part of the json string?

1
  • 1
    If you don't want to declare the extra type you can always use an anonymous struct variable. E.g. var embed struct { TM Events `json:"_embedded"` }. Alternatively you can use a map, E.g. var embed map[string]Events however keep in mind that in this case all of the json's properties must be unmarshallable into the map's element type, that is, the object under "OtherStuff" must also be unmarshallable to Events, if not you'll get an error. Commented Feb 10, 2019 at 23:41

2 Answers 2

1

What you're looking for here is json.RawMessage. It can help delay parsing of certain values, and in you case map[string]json.RawMessage should represent the top-level object where you can selectively parse values. Here's a simplified example you can adjust to your case:

package main

import (
    "encoding/json"
    "fmt"
)

type Event struct {
    Name string `json:"name"`
    Url  string `json:"url"`
}

func main() {
    bb := []byte(`
    {
        "event": {"name": "joe", "url": "event://101"},
        "otherstuff": 15.2,
        "anotherstuff": 100
    }`)

    var m map[string]json.RawMessage
    if err := json.Unmarshal(bb, &m); err != nil {
        panic(err)
    }

    if eventRaw, ok := m["event"]; ok {
        var event Event
        if err := json.Unmarshal(eventRaw, &event); err != nil {
            panic(err)
        }
        fmt.Println("Parsed Event:", event)
    } else {
        fmt.Println("Can't find 'event' key in JSON")
    }
}

In your case look for the _embedded key and then Unmarshal its value to Events

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

Comments

1

yes of course

type Embed struct {
    TM []struct {
        Name  string `json:"name"`
        Url   string `json:"url"`
        Dates struct {
            Start struct {
                LocalDate string
                LocalTime string
            }
        } // add tag here if you want 
    } `json:"_embedded"`
}

Comments

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.