Two Quick Things I learned about JSON in Go

One.

You don’t have to json.Unmarshal into an empty struct. I learned with examples like this:

type Post struct { FavoriteCount int `json:"favorite_count"` ID string `json:"id"` FullText string `json:"full_text"` } exampleJSON := []byte(`{ "id": "098a9df8a90d8fad", "full_text": "Blah blah blah." }`) var post Post err := json.Unmarshal(exampleJSON, &post) if err != nil { fmt.Println(err) }
Code language: Go (go)

There, post is totally defaults, meaning because favorite_count was missing in the JSON data, post.FavoriteCount defaults to 0, the Go default value for an int. But it doesn’t have to start that way! You can Unmarshal it into a variable of that type that isn’t all default values.

post := Post{ FavoriteCount: 5, } err = json.Unmarshal(exampleJSON, &post) if err != nil { fmt.Println(err) }

Now even though the JSON data is still missing favorite_count, the post.FavoriteCount value will be 5. Useful!

And surprising to me, as a language that doesn’t have much in the way of convience methods. Like there certainly is no ...spread like JavaScript, and this feels a smidge like spreading.

Here’s a thing on Replit.

Another thing I need to learn is how to deal better with Unmarshaling data into a struct where the JSON data could be wrong. With the default json.Unmarshal it just totally fails, and so far I’ve worked around it with really permissive temporary types that use a bunch of interface{} shit and coercing it later. But I’d rather use a strict type and deal with it on the spot. I hear userland libs like mapstructure and fastjson can maybe help here.

Two.

Sometimes JSON is all like…

{ "things": {[ "thing: { } ]} }
Code language: JSON / JSON with Comments (json)

And sometimes JSON is all like:

[{ "thing": { } }]
Code language: JSON / JSON with Comments (json)

I was somehow under the wrong impression that the first example was somehow better. It might be in some cases, like where you might use like things_v2 as an opportunity to “version” the JSON, but generally, I actually think the second example is cleaner.

The second is also easier to deal with in Go, as you don’t need an additional “parent” type to deal with “things”. You can just make the main type a []slice and it knows what it’s looking for will be an array in the JSON then.

type testURL struct { Title string `json:"title"` Value string `json:"value"` } exampleJSON := []byte(`[ {"title": "Homepage", "value": "https://nextjs.org/"}, {"title": "GitHub", "value": "https://github.com/vercel/next.js/"}, {"title": "Docs", "value": "https://nextjs.org/docs"} ]`) var allURLs []testURL err := json.Unmarshal(exampleJSON, &allURLs) if err != nil { fmt.Println(err) }
Code language: Go (go)

Here’s a Replit thing.

Leave a Reply

Your email address will not be published.