Jimmy
Jimmy

Reputation: 21

Parsing Nested JSON string

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?

Upvotes: 1

Views: 585

Answers (2)

big pigeon
big pigeon

Reputation: 85

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"`
}

Upvotes: 1

Eli Bendersky
Eli Bendersky

Reputation: 273456

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

Upvotes: 1

Related Questions