Fix #235, casting type to json object
This commit is contained in:
committed by
Steve Chávez
parent
cb2bf809a7
commit
bed1013ecd
@@ -158,6 +158,9 @@ When certain columns are wide (such as those holding binary data), it is more ef
|
|||||||
|
|
||||||
The default is :sql:`*`, meaning all columns. This value will become more important below in :ref:`resource_embedding`.
|
The default is :sql:`*`, meaning all columns. This value will become more important below in :ref:`resource_embedding`.
|
||||||
|
|
||||||
|
Renaming Columns
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
You can rename the columns by prefixing them with an alias followed by the colon ``:`` operator.
|
You can rename the columns by prefixing them with an alias followed by the colon ``:`` operator.
|
||||||
|
|
||||||
.. code-block:: http
|
.. code-block:: http
|
||||||
@@ -169,6 +172,11 @@ You can rename the columns by prefixing them with an alias followed by the colon
|
|||||||
{"fullName": "Jane Doe", "birthDate": "01/12/1998"}
|
{"fullName": "Jane Doe", "birthDate": "01/12/1998"}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
.. _casting_columns:
|
||||||
|
|
||||||
|
Casting Columns
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Casting the columns is possible by suffixing them with the double colon ``::`` plus the desired type.
|
Casting the columns is possible by suffixing them with the double colon ``::`` plus the desired type.
|
||||||
|
|
||||||
.. code-block:: http
|
.. code-block:: http
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
Casting a type to a custom JSON object
|
||||||
|
======================================
|
||||||
|
|
||||||
|
While using PostgREST you might have noticed that certain PostgreSQL types translate to JSON strings when you would
|
||||||
|
have expected a JSON object or array. For example, let's see the case of `range types <https://www.postgresql.org/docs/11/rangetypes.html>`_.
|
||||||
|
|
||||||
|
.. code-block:: postgres
|
||||||
|
|
||||||
|
-- example taken from https://www.postgresql.org/docs/11/rangetypes.html#RANGETYPES-EXAMPLES
|
||||||
|
create table reservations (
|
||||||
|
room int
|
||||||
|
, during tsrange
|
||||||
|
);
|
||||||
|
|
||||||
|
insert into
|
||||||
|
reservations
|
||||||
|
values
|
||||||
|
(1108, tsrange('2010-01-01 14:30', '2010-01-01 15:30'));
|
||||||
|
|
||||||
|
Here we have a column named **during** as a ``tsrange`` type, we would like to get it as JSON through PostgREST.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
curl "http://localhost:3000/reservations"
|
||||||
|
|
||||||
|
Result:
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"room":1108,
|
||||||
|
"during":"[\"2010-01-01 14:30:00\",\"2010-01-01 15:30:00\")"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
The **during** value is probably not the in the format you want. We get a JSON string because by default PostgreSQL casts
|
||||||
|
the type to JSON by using its ``text`` representation. We can change this representation to a custom JSON object by `creating a CAST <https://www.postgresql.org/docs/current/sql-createcast.html>`_ .
|
||||||
|
|
||||||
|
To do this, first we'll define the function that will do the conversion from ``tsrange`` to ``json``.
|
||||||
|
|
||||||
|
.. code-block:: postgres
|
||||||
|
|
||||||
|
create or replace function tsrange_to_json(tsrange) returns json as $$
|
||||||
|
select json_build_object(
|
||||||
|
'lower', lower($1)
|
||||||
|
, 'upper', upper($1)
|
||||||
|
, 'lower_inc', lower_inc($1)
|
||||||
|
, 'upper_inc', upper_inc($1)
|
||||||
|
);
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
|
Using this function we'll create the CAST.
|
||||||
|
|
||||||
|
.. code-block:: postgres
|
||||||
|
|
||||||
|
create cast (tsrange as json) with function tsrange_to_json(tsrange) as assignment;
|
||||||
|
|
||||||
|
And we'll do the request and :ref:`cast the column <casting_columns>`.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
curl "http://localhost:3000/reservations?select=room,during::json"
|
||||||
|
|
||||||
|
The result now is:
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"room":1108,
|
||||||
|
"during":{
|
||||||
|
"lower" : "2010-01-01T14:30:00",
|
||||||
|
"upper" : "2010-01-01T15:30:00",
|
||||||
|
"lower_inc" : true,
|
||||||
|
"upper_inc" : false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
You can use the same idea for creating custom CASTs for different types.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If you don't want to modify CASTs for built-in types, an option would be to `create a custom type <https://www.postgresql.org/docs/current/sql-createtype.html>`_
|
||||||
|
for your own ``tsrange`` and add its own CAST.
|
||||||
|
|
||||||
|
.. code-block:: postgres
|
||||||
|
|
||||||
|
create type mytsrange as range (subtype = timestamp, subtype_diff = tsrange_subdiff);
|
||||||
|
|
||||||
|
-- define column types and casting function analoguously to the above example
|
||||||
|
-- ...
|
||||||
|
|
||||||
|
create cast (mytsrange as json) with function mytsrange_to_json(mytsrange) as assignment;
|
||||||
@@ -16,7 +16,7 @@ And you want to :ref:`embed <resource_embedding>` the **people** table with a **
|
|||||||
|
|
||||||
create schema if not exists private;
|
create schema if not exists private;
|
||||||
|
|
||||||
-- For simplicity's sake the table is devoid of constraints on email, phone, etc.
|
-- For simplicity's sake the table is devoid of constraints/domains on email, phone, etc.
|
||||||
create table private.details(
|
create table private.details(
|
||||||
id int primary key references public.people
|
id int primary key references public.people
|
||||||
, email text
|
, email text
|
||||||
|
|||||||
Reference in New Issue
Block a user