SQLite JSON_SET()

The SQLite json_set() function allows us to insert into, or replace, a value in a JSON document.

We pass the original JSON as the first argument when we call the function, followed by a path that specifies where to insert/replace the new value, followed by the value to insert/replace.

We can also insert/replace multiple key/value pairs if required.

Syntax

It works like this:

json_set(json, path1, value1, path2, value2...)

Where json represents the original JSON, and path1, value1, path2, value2... are path/value pairs that we can use to insert new values into the JSON document (or replace, as the case may be).

Example

Here’s a basic example to demonstrate:

SELECT json_set('{ "a" : 1 }', '$.b', 2);

Result:

{"a":1,"b":2}

Here, I inserted a new key/value pair ("b":2) into the JSON document.

We can insert multiple key/value pairs like this:

SELECT json_set('{ "a" : 1 }', '$.b', 2, '$.c', 3 );

Result:

{"a":1,"b":2,"c":3}

I simply added more key/value arguments when I called json_set().

Replace Values

If the key already exists, its value is replaced with the new value:

SELECT json_set('{ "a" : 1, "b" : 2 }', '$.b', 3);

Result:

{"a":1,"b":3}

This is the main difference between json_set() and json_insert(). The json_insert() function won’t insert the value if the key already exists.

Another way to replace values is to use json_replace().

Insert an Object

Here’s an example of inserting a JSON object:

SELECT json_set('{ "a" : 1 }', '$.b', json('{ "c" : 2 }') );

Result:

{"a":1,"b":{"c":2}}

In this case, I used the json() function to return my argument as a JSON string. Here’s what happens when I don’t do that:

SELECT json_set('{ "a" : 1 }', '$.b', '{ "c" : 2 }' );

Result:

{"a":1,"b":"{ \"c\" : 2 }"}

The JSON document is inserted as a text value instead of a JSON object, and its double quotes are therefore escaped with backslashes.

However, simply removing the single quotes results in an error:

SELECT json_set('{ "a" : 1 }', '$.b', { "c" : 2 } );

Result:

Parse error: unrecognized token: "{"
  SELECT json_set('{ "a" : 1 }', '$.b', { "c" : 2 } );
                          error here ---^

Without single quotes or the json() function, we get an error as soon as it encounters the left curly brace.

Another way to insert a JSON object is to use the json_object() function instead of the json() function:

SELECT json_set('{ "a" : 1 }', '$.b', json_object('c', 2) );

Result:

{"a":1,"b":{"c":2}}

Insert an Array

It’s a similar thing when inserting arrays:

SELECT json_set('{ "a" : 1 }', '$.b', json('[ 2, 3, 4 ]'));

Result:

{"a":1,"b":[2,3,4]}

If we remove the json() function, we get this:

SELECT json_set('{ "a" : 1 }', '$.b', '[ 2, 3, 4 ]');

Result:

{"a":1,"b":"[ 2, 3, 4 ]"}

And if we remove the single quotes, we get an error:

SELECT json_set('{ "a" : 1 }', '$.b', [ 2, 3, 4 ]);

Result:

Parse error: no such column:  2, 3, 4 
  SELECT json_set('{ "a" : 1 }', '$.b', [ 2, 3, 4 ]);
                          error here ---^

We can alternatively use the json_array() function instead of json(). That function allows you to create an array based on its arguments:

SELECT json_set('{ "a" : 1 }', '$.b', json_array( 2, 3, 4 ) );

Result:

{"a":1,"b":[2,3,4]}

Append Values to the end of an Array

We can use json_set() to append values to the end of an array.

To do this, use an array index of [#]:

SELECT json_set('[ 1, 2, 3 ]', '$[#]', 4 );

Result:

[1,2,3,4]

The same principle applies to nested arrays:

SELECT json_set('[ 1, [ "a", "b" ], 3 ]', '$[1][#]', "c" );

Result:

[1,["a","b","c"],3]

Replace Array Elements

We can use json_set() to replace elements in the array:

SELECT json_set('[ 1, 2, 3 ]', '$[1]', 4 );

Result:

[1,4,3]

Arrays are zero based, and so [1] indicates the second array item.

The json_replace() function can also be used to replace existing elements. Again, this is different to json_insert(), which doesn’t replace existing elements.

Invalid Paths

We’ll get an error if our path is not well-formed:

SELECT json_set('{ "a" : 1 }', 'b', 2);

Result:

Runtime error: JSON path error near 'b'

In this case, I forgot to include $. at the front of the path.

Invalid JSON Documents

We’ll also get an error the JSON is not well-formed:

SELECT json_set('{ "a" : 1', '$.b', 2);

Result:

Runtime error: malformed JSON

This time the error tells us that our JSON is malformed.