DEV Community

chris
chris

Posted on

Saving the Marshall in Go

In a previous article, I was discussing appending JSON data in Go and playing a bit around. I would like to expand on it here a little bit more as I kept working on that.

I did some research around marshalling which is the process to export a slice of bytes to a structure, here a JSON structure. The process of formatting your slice of bytes into a structure is called unmarshalling and the opposite marshalling. For that, your programming language is going to parse the input and build it into the desired output.

Unmarshalling is actually the most interesting as Go is parsing every byte and recognizing limiters characters such as quotes (""), colons (:) or brackets ({}) and of course spaces. Each of those characters will define a condition in the process and expect something.

So for example: you have " then your program will expect a string and so on.

As Go is a strongly typed language, you must prepare the receiving end for the unmarshalled structure namely, the exact JSON structure.

Here you have the structure of a cURL on the API of Ergast (a motorsport API) for races:

MRDATA {
    RaceTable {
        Races [
        {
            season
            round
            url
            raceName
            date
            time

            Circuit {

            },
            Results : [
            number,
            position,
            points,
            Driver {}
            Constructor {}
            grid
            laps
            status
            Time {
                millis
                time
            },
            FastestLap {
                rank
                lap
                Time {
                    time
                },
                AverageSpeed {
                    units
                    speed
                },
            },
            ],

        },
        ],
    },
}

Enter fullscreen mode Exit fullscreen mode

The whole result is embedded in the MRData object, so it means that your Go program receiving this will have to mimic this all work. It can be a bit tedious especially with larger API.

So our code to get it would look like:


// Location represents the details of a circuit.
type Location struct {
    Country   string `json:"country"`
    Latitude  string `json:"lat"`
    Locatlity string `json:"locality"`
    Longitude string `json:"long"`
}

// Circuit represents the details of a circuit.
type Circuit struct {
    CircuitID string   `json:"circuitID"`
    URL       string   `json:"url"`
    Name      string   `json:"circuitName"`
    Location  Location `json:"Location"`
}

// Race represents the details of a race.
type Race struct {
    Season   string  `json:"season"`
    Round    string  `json:"round"`
    RaceName string  `json:"raceName"`
    Circuit  Circuit `json:"Circuit"`
    Date     Date    `json:"date"`
    Time     string  `json:"time"`
    URL      string  `json:"url"`
}

// Races is the list of races.
type Races struct {
    Races  []Race `json:"Races"`
    Season string `json:"season"`
}

// RaceTable is the list of races.
type RaceTable struct {
    RaceTable Races `json:"RaceTable"`
}

// MRData is the general wrapper from Eargast API.
type MRData struct {
    MRData RaceTable `json:"MRData"`
}
Enter fullscreen mode Exit fullscreen mode

It is a bit long and the first time, it did took me ages to understand this system. Also, if there are (vim-go)[https://github.com/fatih/vim-go] users, you can add the tags by, after having written the name and type of your structure, running :GoAddTags and magic!

So the whole system of getting data, slice of bytes or API data, into workable JSON structure in Go is to know exactly the input your are going to get. You can trick your system by passing interface{} but it won't be data that you'd be able to work with unfortunately. It is also possible to unmarshall an entire structure in a string but you would end up with the same problem: parsing this. Those workarounds are ok at some point but they defer a bit the point of all this work.

I wanted to mention also the package jsonq which is super helpful to call quickly sub-objects or smaller sub-structure in larger JSON payload.

Thank you for reading and let me know if you have any questions!

Top comments (0)