Go: how to parse arbitrary JSON data

Go: how to parse arbitrary JSON data

How can we parse an arbitrary JSON structure? In Go you can use an alternative solution to structs.

How can we parse an arbitrary JSON structure? In Go you can use an alternative solution to structs.

It is possible to represent the JSON structure with a map whose keys are of type string and whose values are of type interface.


var results map[string]interface{}

This representation can for example be used with a REST API:


package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
)

func apiRequest(query string) (map[string]interface{}, error) {

	var results map[string]interface{}

	baseURL := "https://api.unsplash.com"
	resource := "/search/photos"

	params := url.Values{}
	params.Add("query", query)
	params.Add("client_id", "api_key")

	uri, _ := url.ParseRequestURI(baseURL)
	uri.Path = resource
	uri.RawQuery = params.Encode()

	urlStr := fmt.Sprintf("%v", uri)

	res, err := http.Get(urlStr)

	if err != nil {
	    return results, err
	}

	defer res.Body.Close()

	if res.StatusCode != 200 {
	    return results, errors.New("Request error")
	}

	body, and := io.ReadAll(res.Body)

	if e != nil {
	    return results, e
	}

	jsonData := string(body)

	jsonErr := json.Unmarshal([]byte(jsonData), &results)

	if jsonErr != nil {
   	    return results, jsonErr
	}

	return results, nil
}

func main() {
     results, err := apiRequest("cat")
     if err != nil {
         panic(err)
     }
     fmt.Println(results)
}

In the example we are performing a keyword search with the Unsplash API. The response format is a very complex JSON object that we cannot map to structs in advance. Our generic map, however, allows us to still have a structure on which we can possibly iterate after the response JSON string is passed as a byte slice to the Unmarshal() function.

This is ultimately a useful solution when the JSON structure is very complex.