Postgres JSON functions and how to use them

Postgres JSON functions and how to use them

ยท

8 min read

JSON (JavaScript Object Notation) has grown into a very popular data interchange format that is used in modern web development due to its lightweight, human-readable format. JSON data consists of key-value pairs, similar to a dictionary in Python or an object in JavaScript.

The JSON data format has been supported by Postgres since v9.2. The powerful, open-source relational database management system (RDBMS) has strong support for storing and querying JSON data. In Postgres, the JSON data type allows you to store JSON data in a column and access it using SQL commands. This makes it easy to work with JSON data in a relational database context.

In this blog, we will explore the various functions and techniques that are available in Postgres for working with JSON data. We will cover basic functions for extracting and modifying JSON data, advanced functions for aggregating and validating JSON data, and how to work with JSON data in Python using the psycopg2 library.

Basic JSON Functions

Postgres has support for 2 kinds of JSON data formats: JSON and JSONB. The JSON data type allows you to store JSON data in a column in a table as JSON formatted text. JSONB is an enhanced version of JSON. It stores JSON data in a binary format, which makes it more efficient to query and manipulate. However, it takes up more space on disk and in memory than the JSON data type.

One key difference between JSON and JSONB is that JSONB supports indexing, which can make certain types of queries faster. Another difference is that JSONB supports several additional operators and functions that allow you to manipulate JSON data more easily. For example, the -> operator can be used to extract a value from a JSON object, and the #> operator can be used to extract a value from a JSON object nested within another JSON object.

Overall, JSONB is generally a better choice than JSON if you need to store and manipulate JSON data in your PostgreSQL database. However, if you don't need the additional features and performance of JSONB, and space is a concern, JSON might be a more appropriate choice.

For brevity, we would be referring to both classes of JSON objects as JSON.

To create a JSON column in a table, you can use the following syntax:

Copy code
CREATE TABLE my_table (
    id serial PRIMARY KEY,
    data JSON
);

Once you have a JSON column in your table, you can use various functions to extract data from the JSON values. Some of the most commonly used functions for extracting data from JSON values in Postgres are:

  • >: This function returns the value of a key in a JSON object as a JSON value. For example:
Copy code
SELECT '{"name": "John", "age": 30}'::JSON->'name';

-- Output: "John"
  • >>: This function returns the value of a key in a JSON object as text. For example:
Copy code
SELECT '{"name": "John", "age": 30}'::JSON->>'age';

-- Output: "30"
  • #>: This function allows you to specify a path of keys to extract from a JSON object. For example:
Copy code
SELECT '{"person": {"name": "John", "age": 30}}'::JSON#>'{person,name}';

-- Output: "John"

These functions can be very useful for extracting specific pieces of data from JSON values in your table. In the next section, we will look at more advanced functions for modifying and aggregating JSON data in Postgres.

Advanced JSON Functions

In addition to the basic functions for extracting data from JSON values, Postgres also provides a number of advanced functions for modifying and aggregating JSON data. Here are a few examples:

  • jsonb_set: This function allows you to set the value of a key in a JSON object. It returns the modified JSON object. For example:
Copy code
SELECT jsonb_set('{"name": "John", "age": 30}'::JSONB, '{age}', '40'::JSONB);

-- Output: {"name": "John", "age": 40}
  • jsonb_insert: This function allows you to insert a key-value pair into a JSON object. It returns the modified JSON object. For example:
Copy code
SELECT jsonb_insert('{"name": "John"}'::JSONB, '{email}', '"john@example.com"'::JSONB);

-- Output: {"name": "John", "email": "john@example.com"}
  • jsonb_build_object: This function allows you to build a JSON object from a list of keys and values. It is useful for constructing JSON objects programmatically. For example:
Copy code
SELECT jsonb_build_object('name', 'John', 'age', 30);

-- Output: {"name": "John", "age": 30}

In addition to these functions for modifying JSON data, Postgres also provides functions for aggregating JSON data. Some examples include:

  • jsonb_agg: This function aggregates JSON values into a JSON array. For example:
Copy code
SELECT jsonb_agg(data) FROM my_table;

-- Output: [{"name": "John", "age": 30}, {"name": "Jane", "age": 25}]
  • jsonb_object_agg: This function aggregates key-value pairs into a JSON object. For example:
Copy code
SELECT jsonb_object_agg(key, value) FROM my_table;

-- Output: {"John": {"name": "John", "age": 30}, "Jane": {"name": "Jane", "age": 25}}
  • jsonb_array_elements: This function expands a JSON array into a set of rows. For example:
Copy code
SELECT * FROM jsonb_array_elements('[{"name": "John", "age": 30}, {"name": "Jane", "age": 25}]'::JSONB);

-- Output:
-- name | age
-- -----+-----
-- John | 30
-- Jane | 25

These advanced JSON functions can be very useful for modifying and aggregating JSON data in Postgres.

JSON data validation with check constraints

In addition to the functions for extracting and modifying JSON data, Postgres also provides a way to validate JSON data using check constraints. A check constraint is a rule that specifies the values that are allowed in a column. If a row with an invalid value is inserted or updated, the check constraint will prevent the operation and raise an error.

To add a check constraint to a JSON column in Postgres, you can use the following syntax:

Copy code
ALTER TABLE my_table ADD CONSTRAINT my_constraint CHECK (data @> '{"key": "value"}');

This check constraint will only allow JSON objects that contain a key "key" with the value "value". You can use more complex expressions in the check constraint to enforce specific data types and structures in the JSON data. For example, to ensure that a key "age" is an integer, you can use the following constraint:

Copy code
ALTER TABLE my_table ADD CONSTRAINT age_constraint CHECK (data->'age'::text ~ E'^\\\\d+$');

This constraint will only allow integers for the "age" key. You can use similar expressions to enforce other data types and structures in the JSON data.

Check constraints are a useful way to ensure that the JSON data in your table meets specific requirements. They can help prevent data inconsistencies and errors, and make it easier to work with JSON data in your application.

Working with JSON data in Python

Postgres provides native support for Python through the psycopg2 library, which allows you to connect to a Postgres database and execute SQL commands using Python. This can be very useful for working with JSON data in Postgres, as you can use the powerful data manipulation and analysis tools in Python to process and analyze your JSON data.

To get started with psycopg2, you will need to install it using pip:

Copy code
pip install psycopg2

Once you have psycopg2 installed, you can connect to a Postgres database using the following code:

Copy code
import psycopg2

conn = psycopg2.connect(
    host="localhost",
    port=5432,
    user="user",
    password="password",
    database="database"
)

This will establish a connection to the Postgres database specified in the connection parameters. You can then use this connection to execute SQL commands using the cursor object:

Copy code
cursor = conn.cursor()

cursor.execute("SELECT * FROM my_table")

print(cursor.fetchall())

This will execute the SQL command SELECT * FROM my_table and print the results.

To work with JSON data in Python, you can use the json module to parse and serialize JSON data. For example, to insert a JSON object into a JSON column in Postgres, you can use the following code:

Copy code
import json

data = { "name": "John", "age": 30 }

cursor.execute("INSERT INTO my_table (data) VALUES (%s)", (json.dumps(data),))

conn.commit()

This will insert the JSON object {"name": "John", "age": 30} into the data column in the my_table table.

You can also use psycopg2 and the json module to update and query JSON data in Postgres. For example, to update a JSON object in a table, you can use the following code:

Copy code
cursor.execute("UPDATE my_table SET data = %s WHERE id = %s", (json.dumps(new_data), id))

conn.commit()

This will update the data column for the row with the specified id with the JSON object new_data.

To query JSON data in Postgres using psycopg2, you can use the -> and ->> functions in your SQL queries to extract JSON data as Python objects. For example:

Copy code
cursor.execute("SELECT id, data->>'name' FROM my_table")

results = cursor.fetchall()

for result in results:
    print(result[0], result[1])

This will retrieve the id and name fields from the data column in the my_table table, and print them as Python objects.

Using psycopg2 and the json module, you can easily work with JSON data in Postgres from within your Python application. In the next section, we will conclude our discussion of working with JSON data in Postgres.

Summary

To summarize, here are the main functions and techniques that we covered for working with JSON data in Postgres:

  • >: Extracts a JSON value as a JSON object

  • >>: Extracts a JSON value as text

  • #>: Extracts a JSON value using a path of keys

  • jsonb_set: Sets the value of a key in a JSON object

  • jsonb_insert: Inserts a key-value pair into a JSON object

  • jsonb_build_object: Builds a JSON object from a list of keys and values

  • jsonb_agg: Aggregates JSON values into a JSON array

  • jsonb_object_agg: Aggregates key-value pairs into a JSON object

  • jsonb_array_elements: Expands a JSON array into a set of rows

  • Check constraints: Validates JSON data using a specified rule

  • psycopg2: Connects to a Postgres database and executes SQL commands using Python

  • json module: Parses and serializes JSON data in Python

These functions and techniques can be very useful for working with JSON data in Postgres and building applications that rely on JSON data.

Did you find this article valuable?

Support Chinaza Egbo by becoming a sponsor. Any amount is appreciated!