Not sure how to structure your Go web application?
My new book guides you through the start-to-finish build of a real world web application in Go — covering topics like how to structure your code, manage dependencies, create dynamic database-driven pages, and how to authenticate and authorize users securely.
PostgreSQL provides two JSON-related data types that you can use — JSON and JSONB. The principal differences are:
JSON stores an exact copy of the JSON input.
JSONB stores a binary representation of the JSON input. This makes it slower to insert but faster to query. It may change the key order, and will remove whitespace and delete duplicate keys. JSONB also supports the ? (existence) and @> (containment) operators, whereas JSON doesn't.
The PostgreSQL documentation recommends that you should generally use JSONB, unless you have a specific reason not too (like needing to preserve key order).
Here's a cribsheet for the essential commands:
For a full description of all available operators please see the official JSON Functions and Operators documentation.
Using with Go
If your not familiar with the general patterns for working with SQL databases in Go, you might want to read my introduction to the database/sql package before continuing.
Known JSON fields
When the fields in a JSON/JSONB column are known in advance, you can map the contents of the JSON/JSONB column to and from a struct. To do this, you'll need make sure the struct implements:
The driver.Valuer interface, such that it marshals the object into a JSON byte slice that can be understood by the database.
The sql.Scanner interface, such that it unmarshals a JSON byte slice from the database into the struct fields.
Here's a demonstration:
Unknown JSON fields
The above pattern works great if you know in advance what keys and values your JSON/JSONB data will contain. And it has the major advantage of being type safe.
For the times that you don't know this in advance (for example, the data contains user-generated keys and values) you can map the contents of the JSON/JSONB column to and from a map[string]interface{} instead. The big downside of this is that you will need to type assert any values that you retrieve from the database in order to use them.
Here's the same example, but re-written to use a map[string]interface{}:
If you enjoyed this article, you might like to check out my recommended tutorials list or check out my books Let's Go and Let's Go Further, which teach you everything you need to know about how to build professional production-ready web applications and APIs with Go.