Commit c3e64a71 authored by Shane A. Stillwell's avatar Shane A. Stillwell 🎯

post on postgres to_json

parent 2dc98ed3
---
title: "The Wonderful and Dangerous to_json from Postgres"
date: 2018-10-31T08:39:02-05:00
draft: true
tags:
- postgresql
---
......@@ -16,7 +15,8 @@ Let's take a look at how to use `to_json` in your queries. A really simple examp
CREATE TABLE company (
id SERIAL PRIMARY KEY,
name text,
website text
website text,
range int4range
);
CREATE UNIQUE INDEX company_pkey ON company(id int4_ops);
......@@ -28,10 +28,10 @@ CREATE TABLE person (
);
CREATE UNIQUE INDEX person_pkey ON person(id int4_ops);
INSERT INTO "public"."company"("id","name","website")
INSERT INTO "public"."company"("id","name","website","range")
VALUES
(1,E'Apple',E'www.apple.com'),
(2,E'Google',E'www.google.com');
(1,E'Apple',E'www.apple.com',E'[100,150)'),
(2,E'Google',E'www.google.com',E'[80,120)');
INSERT INTO "public"."person"("id","name","phone","company_id")
VALUES
......@@ -54,14 +54,14 @@ This gives us a nice JSON array of results
{
"id" : 1,
"phone" : "3035551212",
"company" : {"id":1, "name":"Apple", "website":"www.apple.com"},
"company" : {"id":1,"name":"Apple","website":"www.apple.com","range":"[100,150)"},
"name" : "Shane",
"company_id" : 1
},
{
"id" : 2,
"phone" : "4045551212",
"company" : {"id":2, "name":"Google", "website":"www.google.com"},
"company" : {"id":2,"name":"Google","website":"www.google.com","range":"[80,120)"},
"name" : "Larry",
"company_id" : 2
}
......@@ -74,11 +74,15 @@ Do you see how we get a nice JSON array with nested values for the `person.compa
## What's so Dangerous?
Glad you asked. By converting the rows you return to JSON, you lose the specific types of the fields. Now the `company` field is JSON and the items within just use primitive JSON types (string, numbers, boolean, arrays, objects). Now you lose any type of specific postgres driver sugar.
Glad you asked. By converting the rows you return to JSON, you lose the specific types of the fields. Now the `company` field is JSON and the items within just use primitive JSON types (string, numbers, boolean, arrays, objects). You lose any data type hints for the postgres client driver to utilize. This is true for dates, dates with timestamps, integers, floats, and any other postgres data type that is not just a JSON primitive. Looks specifically at the `company.range` field. For all the client knows, it's just a text field, it doesn't know it's actually an `int4range` field type.
### An Example in a current app
### An Example in a current app
I'm working on a app utilizing the PG [Range Types](https://www.postgresql.org/docs/9.3/static/rangetypes.html). In this instances, it's the `int4range` type to signify age ranges. For example, it might have age range values of `[0, 10)`, or `[10, 15)`, or `[15, 100)`. This is **range type** literal notation for *Number range begining at 0 and ending on 9*. I also use a really handy Node.js postgres tool [pg-range](https://www.npmjs.com/package/pg-range), it will detect a range field and automagically parse the field into other properties, such as `begin`, `end`, and some nice comparison methods.
The problem, when I use `to_json`, the fields returned for `age_range` is not a `int4range`, but rather a `text` data type. Therefor, it doesn't get converted by the *pg-range* driver and I lose the ability to call `.begin` or `.end` on that field.
## Conclusion
By all means, use `to_json` and `json_agg` to your advantage and leverage their power. You just need to be careful you understand you're getting back JSON and not real workable Postgres values.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment