DEV Community

Mohamed Shapan
Mohamed Shapan

Posted on

Golang how to unmarshal a subset of nested JSON data

Have you ever face a case when you need to get nested data from a JSON object?

I think we face this scenario all the time when we deal with third-party APIs

regularly we use JSON unmarshaling to a struct that contains another struct was the only obvious way,

But today I'm happy to introduce a new option with NJSON package, an option that gives us the ability and flexibility to unmarshal any nested JSON without creating nested objects, just by it's JSON path

For example

we are trying to unmarshal this JSON string

{
    "coord": {
        "lon": -0.13,
        "lat": 51.51
    },
    "weather": [
        {
            "id": 300,
            "main": "Drizzle",
            "description": "light intensity drizzle",
            "icon": "09d"
        }
    ],
    "base": "stations",
    "main": {
        "temp": 280.32,
        "pressure": 1012,
        "humidity": 81,
        "temp_min": 279.15,
        "temp_max": 281.15
    },
    "visibility": 10000,
    "wind": {
        "speed": 4.1,
        "deg": 80
    },
    "clouds": {
        "all": 90
    },
    "dt": 1485789600,
    "sys": {
        "type": 1,
        "id": 5091,
        "message": 0.0103,
        "country": "GB",
        "sunrise": 1485762037,
        "sunset": 1485794875
    },
    "id": 2643743,
    "name": "London",
    "cod": 200
}

(JSON from openweathermap)

To weather overview struct like this
type Weather struct {
    Location       string  
    Weather        string  
    Description    string  
    Temperature    float32 
    MinTemperature float32 
    MaxTemperature float32 
}



Using the standard JSON package we are going to unmarshal it then restructure it like this

    type Weather struct {
        Location       string
        Weather        string
        Description    string
        Temperature    float32
        MinTemperature float32
        MaxTemperature float32
    }

    type TmpWeather struct {
        Location string `json:"name"`
        Weather  []struct {
            Weather     string `json:"main"`
            Description string `json:"description"`
        } `json:"weather"`
        Temperature struct {
            Temperature    float32 `json:"temp"`
            MinTemperature float32 `json:"temp_min"`
            MaxTemperature float32 `json:"temp_max"`
        } `json:"main"`
    }

    var tmpW TmpWeather
    err := json.Unmarshal([]byte(jsonString), &tmpW)
    if err != nil {
        panic(err)
    }

    fmt.Printf("%+v\n", tmpW)
    // {Location:London Weather:[{Weather:Drizzle Description:light intensity drizzle}] Temperature:{Temperature:280.32 MinTemperature:279.15 MaxTemperature:281.15}}

    weather := Weather{
        Location:       tmpW.Location,
        Weather:        tmpW.Weather[0].Weather,
        Description:    tmpW.Weather[0].Description,
        Temperature:    tmpW.Temperature.Temperature,
        MinTemperature: tmpW.Temperature.MinTemperature,
        MaxTemperature: tmpW.Temperature.MaxTemperature,
    }

    fmt.Printf("%+v\n", weather)
    // {Location:London Weather:Drizzle Description:light intensity drizzle Temperature:280.32 MinTemperature:279.15 MaxTemperature:281.15}



With NJSON all we need to do is just add njson tag to struct
then unmarshal it using NJSON like this

    type Weather struct {
        Location       string  `njson:"name"`
        Weather        string  `njson:"weather.0.main"`
        Description    string  `njson:"weather.0.description"`
        Temperature    float32 `njson:"main.temp"`
        MinTemperature float32 `njson:"main.temp_min"`
        MaxTemperature float32 `njson:"main.temp_max"`
    }

    var weather Weather
    err := njson.Unmarshal([]byte(jsonString), &weather)
    if err != nil {
        panic(err)
    }

    fmt.Printf("%+v\n", weather)
    // {Location:London Weather:Drizzle Description:light intensity drizzle Temperature:280.32 MinTemperature:279.15 MaxTemperature:281.15}



Wrapping up
I hope you like NJSON, for more details you can visit NJSON GitHub repo, you can find the complete example Here and for any feedback don't hesitate to contact me on twitter @m7shapan

Top comments (1)

Collapse
 
ankogit profile image
Anatoliy Antoneko

Thanks!