JSON in 9.2 - Could we have just one to_json() function instead of two separate versions ?
Hi hackers
After playing around with array_to_json() and row_to_json() functions a
bit it I have a question - why do we even have 2 variants *_to_json()
Collapsing array_to_json() and row_to_json() into just to_json()
----------------------------------------------------------------
As the functionality is not yet release maybe we could still rethink the
interface and have just one which can deal with all types :
to_json(any) returns json
the current two versions have to call the "any" variant internally
anyhow, to convert individual field values, so why not just expose the
full functionality as a single to_json() function
You almost can get the "any" functionality now by wrapping the type in
an array and afterwards strip outermost [] from the result.
Is there any good reason why not expose any_to_json() it directly ?
CREATE OR REPLACE FUNCTION to_json(obj anyelement)
RETURNS json AS $$
BEGIN
RETURN substring(array_to_json(array[obj])::text FROM '^\[(.*)\]$');
END;
$$ LANGUAGE plpgsql;
hannu=# select to_json('1'::text) ;
to_json
---------
"1"
(1 row)
hannu=# select to_json(test) from test limit 2;
to_json
-------------------------------------------------------------------
{"id":9,"data":"testdata","tstamp":"2012-05-01 09:44:50.175189"}
{"id":10,"data":"testdata","tstamp":"2012-05-01 09:45:50.260276"}
(2 rows)
Maybe we can remove the *_to_json(functions completely :)
---------------------------------------------------------
As a separate note, could we go even further and fold all this
functionality into an universal cast, so that attaching ::json to any
object will automagically work ?
Removing current limitation of PL/pgSQL
----------------------------------------
The above plpgsql definition of to_json() does not currently work with
anonymous records defined inline or arrays of such records, but only
because Pl/PgSQL functions currently don't accept these types
hannu=# select to_json(s) from (select 1::int as i, 't'::text as t union
select 2,'x')s;
ERROR: PL/pgSQL functions cannot accept type record
CONTEXT: compilation of PL/pgSQL function "to_json" near line 1
I think PL/pgSQL could now start accepting such records as the wrinkles
which made it hard to (recursively) get the needed info for anonymous
records were ironed out when developing the *_to_json() functions so all
of it just works.
IIRC some of this needed improving data available in core, and was not
just extra surgery done directly inside the *_to_json() functions.
hannu=# select row_to_json(s) from (select 1::int as i, 't'::text as t
union select 2,'x')s;
row_to_json
-----------------
{"i":1,"t":"t"}
{"i":2,"t":"x"}
(2 rows)
and even
hannu=# select row_to_json(s) from (select 1::int as i, (select z
from(select 2::int as j, 'x'::text as x)z) as t union select 2,null)s;
row_to_json
-----------------------------
{"i":1,"t":{"j":2,"x":"x"}}
{"i":2,"t":null}
(2 rows)
--
-------
Hannu Krosing
PostgreSQL Unlimited Scalability and Performance Consultant
2ndQuadrant Nordic
PG Admin Book: http://www.2ndQuadrant.com/books/
On Tue, May 1, 2012 at 7:02 AM, Hannu Krosing <hannu@2ndquadrant.com> wrote:
Hi hackers
After playing around with array_to_json() and row_to_json() functions a
bit it I have a question - why do we even have 2 variants *_to_json()Collapsing array_to_json() and row_to_json() into just to_json()
I asked the same question. It was noted that the xml functions aren't
overloaded like that and that it's cleaner to introduce datum specific
behaviors if you don't overload.
I don't really agree with that or any of the naming styles that are in
the form inputtype_func() but I think most people are on the other
side of the argument.
merlin
On Tue, 2012-05-01 at 08:18 -0500, Merlin Moncure wrote:
On Tue, May 1, 2012 at 7:02 AM, Hannu Krosing <hannu@2ndquadrant.com> wrote:
Hi hackers
After playing around with array_to_json() and row_to_json() functions a
bit it I have a question - why do we even have 2 variants *_to_json()Collapsing array_to_json() and row_to_json() into just to_json()
I asked the same question. It was noted that the xml functions aren't
overloaded like that and that it's cleaner to introduce datum specific
behaviors if you don't overload.
XML, being an "enterprise" thing is a large and complex beast.
Javascript - and by extension json - comes from the other end, being
lightweight and elegant at core.
Also, the the *_to_xml functions present still don't match what is there
for json, they don't even overlap !
Thus I see no reason why deciding on how to_json() functions (or cast to
json) should work needs to be based on how xml works.
We currently don't have any of the "database_to_json()" or
"querystring_to_json()" and we don't need these either.
I'd be much more happy by just having a working cast to json from all
types, not a myriad of functions for all possible types -
int4_to_json(), text_to_json(), bool_to_json(), record_to_json(),
array_to_json(), pg_user_to_json, etc. etc. etc.
What we currently have exposed to userspace are two arbitrarily chosen
"compex type" functions -
array_to_json() for converting arrays of ANY element type to json ,
inluding arrays consisting of records which may again contain arrays and
records.
and
row_to_json() for converting "rows" again potentially consisting of ANY
TYPE, including arrays of any type and any complex type. It handles even
the row() type :)
hannu=# select row_to_json(row(1,2,3));
row_to_json
------------------------
{"f1":1,"f2":2,"f3":3}
(1 row)
What we currently lack is direct conversion for simple types, though
they are easily achieved by converting to a single-element array and
then stripping outer [] from the result
It would be really nice to also have the casts from json to any type,
including records though.
And perhaps one functions for converting schema elements to some json
representation, so that a json_dump could easily be constructed :)
We really do not need footguns similar to database_to_xml() or
schema_to_xml() which just to consume all memory in the server on any
real database.
I don't really agree with that or any of the naming styles that are in
the form inputtype_func() but I think most people are on the other
side of the argument.
I think that most people have not given this any thought yet, so they
simply lack any reasoned opinion ;)
merlin
--
-------
Hannu Krosing
PostgreSQL Unlimited Scalability and Performance Consultant
2ndQuadrant Nordic
PG Admin Book: http://www.2ndQuadrant.com/books/
On Tue, May 1, 2012 at 8:02 AM, Hannu Krosing <hannu@2ndquadrant.com> wrote:
Hi hackers
After playing around with array_to_json() and row_to_json() functions a
bit it I have a question - why do we even have 2 variants *_to_json()
Here's the discussion where that decision was made:
http://archives.postgresql.org/pgsql-hackers/2012-01/msg01339.php
To quote:
why not call all these functions 'to_json' and overload them?
I don't honestly feel that advances clarity much. And we might want to overload each at some stage with options that are specific to the datum type. We have various foo_to_xml() functions now.
-1
older proposal is more consistent with xml functions
The most compelling argument I see here is the one about options
specific to the datum type.
Two other reasons I can think of:
* If someone tries to google for how to convert an array to JSON,
having a function named 'array_to_json' will make that easier.
* If the JSON type does not yet support, say, converting from a
number, it will be apparent from the names and types of the functions,
rather than being a hidden surprise. On the other hand, array_to_json
and composite_to_json already convert ANY values to JSON, so this
doesn't matter, anyway.
On Tue, May 1, 2012 at 11:02 AM, Hannu Krosing <hannu@2ndquadrant.com> wrote:
What we currently lack is direct conversion for simple types, though
they are easily achieved by converting to a single-element array and
then stripping outer [] from the result
I agree that this function ought to be exposed. Note that such a
function (perhaps called datum_to_json) is indeed the same as the
proposed to_json function, which tries to convert a value of any type
to JSON.
It would be really nice to also have the casts from json to any type,
including records though.
What the casts currently do (primarily) is convert between the TEXT
and JSON types. So if you have JSON-encoded TEXT, use a cast to
convert it to the JSON type (this will perform validation, ensuring
that no invalid JSON gets in). Any escape/unescape operations need to
be explicit.
-Joey
On Tue, May 1, 2012 at 10:49 AM, Joey Adams <joeyadams3.14159@gmail.com> wrote:
On Tue, May 1, 2012 at 8:02 AM, Hannu Krosing <hannu@2ndquadrant.com> wrote:
Hi hackers
After playing around with array_to_json() and row_to_json() functions a
bit it I have a question - why do we even have 2 variants *_to_json()Here's the discussion where that decision was made:
http://archives.postgresql.org/pgsql-hackers/2012-01/msg01339.php
To quote:
why not call all these functions 'to_json' and overload them?
I don't honestly feel that advances clarity much. And we might want to overload each at some stage with options that are specific to the datum type. We have various foo_to_xml() functions now.
-1
older proposal is more consistent with xml functions
The most compelling argument I see here is the one about options
specific to the datum type.
I don't find that to be particularly compelling at all. to_timestamp
for example supports multiple argument versions depending on the input
type.
* If the JSON type does not yet support, say, converting from a
number, it will be apparent from the names and types of the functions,
rather than being a hidden surprise. On the other hand, array_to_json
and composite_to_json already convert ANY values to JSON, so this
doesn't matter, anyway.
I don't see how not having to_json(type) is any less surprising than
type_to_json().
To add:
Are we going to have json_length()? Why shouldn't length operate
directly on the json type since it has a length? Or are we going to
force an implicit cast to text?
An elementary point of generic programming through SQL is that you are
supposed to keep *what you are trying to do* decoupled from *what
you're doing it on*. It allows for very natural and terse
programming. The array, xml, and now the json apis essentially
violate this principle. The array api I find particularly galling
since you end up having to retype 'array' N times in a single
expression.
merlin
On Tue, 2012-05-01 at 11:49 -0400, Joey Adams wrote:
On Tue, May 1, 2012 at 8:02 AM, Hannu Krosing <hannu@2ndquadrant.com> wrote:
Hi hackers
After playing around with array_to_json() and row_to_json() functions a
bit it I have a question - why do we even have 2 variants *_to_json()Here's the discussion where that decision was made:
http://archives.postgresql.org/pgsql-hackers/2012-01/msg01339.php
Thanks, will read it!
To quote:
why not call all these functions 'to_json' and overload them?
I don't honestly feel that advances clarity much. And we might want
to overload each at some stage with options that are specific to the
datum type. We have various foo_to_xml() functions now.-1
older proposal is more consistent with xml functions
The most compelling argument I see here is the one about options
specific to the datum type.Two other reasons I can think of:
* If someone tries to google for how to convert an array to JSON,
having a function named 'array_to_json' will make that easier.
Well, if you want to know how to convert an integer to string, you don't
use integer_to_text() function. you just use a working cast.
and here it is an outright lie:
hannu=# select 1::json;
ERROR: cannot cast type integer to json
LINE 1: select 1::json;
the error should be "won't cast type integer to json" :)
It very well _can_ convert it, as it does it without a problem when such
integer is inside an array or a record type.
* If the JSON type does not yet support, say, converting from a
number, it will be apparent from the names and types of the functions,
rather than being a hidden surprise. On the other hand, array_to_json
and composite_to_json already convert ANY values to JSON, so this
doesn't matter, anyway.
By this logic all non-working casts are "hidden surprises"
On Tue, May 1, 2012 at 11:02 AM, Hannu Krosing <hannu@2ndquadrant.com> wrote:
What we currently lack is direct conversion for simple types, though
they are easily achieved by converting to a single-element array and
then stripping outer [] from the resultI agree that this function ought to be exposed. Note that such a
function (perhaps called datum_to_json) is indeed the same as the
proposed to_json function, which tries to convert a value of any type
to JSON.
Hmm, I just have found an answer to my question on how to add to_json()
capability to extension types .
If whe had to_json as a cast, it would probably be straightforward for
extensions like hstore to provide their own to_json casts - especially
now that the json type is in core - and we could get a working hstore
--> json conversion by just running the
CREATE EXTENSION hstore;
command.
It would be really nice to also have the casts from json to any type,
including records though.What the casts currently do (primarily) is convert between the TEXT
and JSON types. So if you have JSON-encoded TEXT, use a cast to
convert it to the JSON type (this will perform validation, ensuring
that no invalid JSON gets in). Any escape/unescape operations need to
be explicit.-Joey
--
-------
Hannu Krosing
PostgreSQL Unlimited Scalability and Performance Consultant
2ndQuadrant Nordic
PG Admin Book: http://www.2ndQuadrant.com/books/
On Tue, May 1, 2012 at 9:05 AM, Merlin Moncure <mmoncure@gmail.com> wrote:
On Tue, May 1, 2012 at 10:49 AM, Joey Adams <joeyadams3.14159@gmail.com>
wrote:On Tue, May 1, 2012 at 8:02 AM, Hannu Krosing <hannu@2ndquadrant.com>
wrote:
Hi hackers
After playing around with array_to_json() and row_to_json() functions a
bit it I have a question - why do we even have 2 variants *_to_json()Here's the discussion where that decision was made:
http://archives.postgresql.org/pgsql-hackers/2012-01/msg01339.php
To quote:
why not call all these functions 'to_json' and overload them?
I don't honestly feel that advances clarity much. And we might want to
overload each at some stage with options that are specific to the datum
type. We have various foo_to_xml() functions now.-1
older proposal is more consistent with xml functions
The most compelling argument I see here is the one about options
specific to the datum type.I don't find that to be particularly compelling at all. to_timestamp
for example supports multiple argument versions depending on the input
type.* If the JSON type does not yet support, say, converting from a
number, it will be apparent from the names and types of the functions,
rather than being a hidden surprise. On the other hand, array_to_json
and composite_to_json already convert ANY values to JSON, so this
doesn't matter, anyway.
I am away from base on a consulting assignment all this week, so my
connectivity and time are severely limited, and I don't have time to
respond in depth.
Let me just point out two things. First, we are approaching a beta release.
The time for changing this is long since gone, IMNSHO.
Second, RFC 4627 is absolutely clear: a valid JSON value can only be an
object or an array, so this thing about converting arbitrary datum values
to JSON is a fantasy. If anything, we should adjust the JSON input routines
to disallow anything else, rather than start to output what is not valid
JSON.
cheers
andrew
On Tue, May 1, 2012 at 11:22 AM, Andrew Dunstan <andrew@dunslane.net> wrote:
On Tue, May 1, 2012 at 9:05 AM, Merlin Moncure <mmoncure@gmail.com> wrote:
On Tue, May 1, 2012 at 10:49 AM, Joey Adams <joeyadams3.14159@gmail.com>
wrote:On Tue, May 1, 2012 at 8:02 AM, Hannu Krosing <hannu@2ndquadrant.com>
wrote:Hi hackers
After playing around with array_to_json() and row_to_json() functions a
bit it I have a question - why do we even have 2 variants *_to_json()Here's the discussion where that decision was made:
http://archives.postgresql.org/pgsql-hackers/2012-01/msg01339.php
To quote:
why not call all these functions 'to_json' and overload them?
I don't honestly feel that advances clarity much. And we might want to
overload each at some stage with options that are specific to the datum
type. We have various foo_to_xml() functions now.-1
older proposal is more consistent with xml functions
The most compelling argument I see here is the one about options
specific to the datum type.I don't find that to be particularly compelling at all. to_timestamp
for example supports multiple argument versions depending on the input
type.* If the JSON type does not yet support, say, converting from a
number, it will be apparent from the names and types of the functions,
rather than being a hidden surprise. On the other hand, array_to_json
and composite_to_json already convert ANY values to JSON, so this
doesn't matter, anyway.I am away from base on a consulting assignment all this week, so my
connectivity and time are severely limited, and I don't have time to respond
in depth.Let me just point out two things. First, we are approaching a beta release.
The time for changing this is long since gone, IMNSHO.
sure. pedantic philosophical arguments aside, I'm already using the
api heavily and would prefer not to see it changed :-).
merlin
Andrew Dunstan <andrew@dunslane.net> writes:
Let me just point out two things. First, we are approaching a beta release.
The time for changing this is long since gone, IMNSHO.
This is our last chance to get it right, so that argument doesn't seem
to me to carry a lot of weight ...
Second, RFC 4627 is absolutely clear: a valid JSON value can only be an
object or an array, so this thing about converting arbitrary datum values
to JSON is a fantasy. If anything, we should adjust the JSON input routines
to disallow anything else, rather than start to output what is not valid
JSON.
... but this one does.
regards, tom lane
On Tue, May 1, 2012 at 12:22 PM, Andrew Dunstan <andrew@dunslane.net> wrote:
Second, RFC 4627 is absolutely clear: a valid JSON value can only be an
object or an array, so this thing about converting arbitrary datum values to
JSON is a fantasy. If anything, we should adjust the JSON input routines to
disallow anything else, rather than start to output what is not valid JSON.
No, the RFC says (emphasis mine):
A JSON *text* is a serialized object or array.
If we let the JSON type correspond to a *value* instead, this
restriction does not apply, and the JSON type has a useful recursive
definition.
For example, this function would not be possible if we applied the
"object or array" restriction:
unnest(json) returns setof json
Note that a similar distinction appears with the XML type: "document"
versus "content".
-Joey
On Tue, May 1, 2012 at 9:56 AM, Joey Adams <joeyadams3.14159@gmail.com>wrote:
On Tue, May 1, 2012 at 12:22 PM, Andrew Dunstan <andrew@dunslane.net>
wrote:Second, RFC 4627 is absolutely clear: a valid JSON value can only be an
object or an array, so this thing about converting arbitrary datumvalues to
JSON is a fantasy. If anything, we should adjust the JSON input routines
to
disallow anything else, rather than start to output what is not valid
JSON.
No, the RFC says (emphasis mine):
A JSON *text* is a serialized object or array.
If we let the JSON type correspond to a *value* instead, this
restriction does not apply, and the JSON type has a useful recursive
definition.For example, this function would not be possible if we applied the
"object or array" restriction:unnest(json) returns setof json
Note that a similar distinction appears with the XML type: "document"
versus "content".
I think you're playing with words. But in any case, the RFC says this
regarding generators:
5. Generators
A JSON generator produces JSON text. The resulting text MUST
strictly conform to the JSON grammar.
Our functions do seem to be JSON generators. So even if we accept
things that aren't JSON texts in our parser (possibly permitted by
section 4 of the RFC) we should not be generating them.
cheers
andrew
On Tue, 2012-05-01 at 12:54 -0400, Tom Lane wrote:
Andrew Dunstan <andrew@dunslane.net> writes:
Let me just point out two things. First, we are approaching a beta release.
The time for changing this is long since gone, IMNSHO.This is our last chance to get it right, so that argument doesn't seem
to me to carry a lot of weight ...Second, RFC 4627 is absolutely clear: a valid JSON value can only be an
object or an array,
No, according to RFC, a valid "JSON value" can be:
an object, an array, a number, a string, or one of false null true
From RFC:
-------------------------
1. Introduction
JavaScript Object Notation (JSON) is a text format for the
serialization of structured data. It is derived from the object
literals of JavaScript, as defined in the ECMAScript Programming
Language Standard, Third Edition [ECMA].
JSON can represent four primitive types (strings, numbers, booleans,
and null) and two structured types (objects and arrays).
...
2.1. Values
A JSON value MUST be an object, array, number, or string, or one of
the following three literal names:
false null true
-------------------------
By having our JSON type mean a "JSON value" instead of "JSON
text" (which indeed is required to be array or object) we could make it
easy for all extension types to provide casts to "JSON value" and thus
automatically plug them into postgreSQL's built-in JSON support.
I would very much like this the *_to_array() functions first try a cast
to json when converting values, so that for example after the following
cast it would do the right thing for hstore .
CREATE FUNCTION hstore_to_json(IN hvalue hstore, OUT jvalue json) AS $$
return '{%s}' % hvalue.replace('"=>"','":"')
$$ LANGUAGE plpythonu;
CREATE CAST (hstore AS json)
WITH FUNCTION hstore_to_json(hstore)
AS IMPLICIT
;
hannu=# select *, datadict::json from test_hstore;
id | datadict | datadict
----+---------------------------------+---------------------------------
1 | "baz"=>"whatever", "foo"=>"bar" | {"baz":"whatever", "foo":"bar"}
2 | "bar"=>"the same", "foo"=>"bar" | {"bar":"the same", "foo":"bar"}
(2 rows)
Currently it seems to be hardwired to do datum --> text conversions
hannu=# select row_to_json(test_hstore) from test_hstore;
row_to_json
---------------------------------------------------------------
{"id":1,"datadict":"\"baz\"=>\"whatever\", \"foo\"=>\"bar\""}
{"id":2,"datadict":"\"bar\"=>\"the same\", \"foo\"=>\"bar\""}
(2 rows)
I'd like it to try datum --> json first and yield
hannu=# select row_to_json(test_hstore) from test_hstore;
row_to_json
---------------------------------------------------------------
{"id":1,"datadict":{"baz":"whatever", "foo":"bar"}}
{"id":2,"datadict":{"bar":"the same", "foo":"bar"}}
(2 rows)
This exact case could be made to work even with "JSON text" meaning ob
json type, but some other types may not be so lucky.
FOr example imagine a tri-value booean with textual values "yes", "no",
and "don't know" . Logical mapping to json would be true, false, null,
but we can't easily provide a triboolean --> json cast for this if we
require json value to be "JSON text" and don't accept "JSON values"
so this thing about converting arbitrary datum values
to JSON is a fantasy.
It should be possible to cast them to "JSON value", but not always "JSON
text" which indeed has to be array or object .
If anything, we should adjust the JSON input routines
to disallow anything else, rather than start to output what is not valid
JSON.
Nah, I'd like us to accept what other JSON parsers usually accept,
especially the original one described in
http://www.json.org/fatfree.html which cited one way to parse json to be
responseData = eval('(' + responseText + ')');
:)
But then I also like their statement when comparing JSON to XML :
JSON has no validator. Being well-formed and valid is not the same as
being correct and relevant. Ultimately, every application is responsible
for validating its inputs. This cannot be delegated.
... but this one does.
It does, _if_ we accept that json type is for "JSON text" and not "JSON
value". in which case we might need also a json_value type for
extensible casting to and from json.
regards, tom lane
--
-------
Hannu Krosing
PostgreSQL Unlimited Scalability and Performance Consultant
2ndQuadrant Nordic
PG Admin Book: http://www.2ndQuadrant.com/books/
On Tue, 2012-05-01 at 11:11 -0700, Andrew Dunstan wrote:
On Tue, May 1, 2012 at 9:56 AM, Joey Adams
<joeyadams3.14159@gmail.com> wrote:
...
No, the RFC says (emphasis mine):
A JSON *text* is a serialized object or array.
If we let the JSON type correspond to a *value* instead, this
restriction does not apply, and the JSON type has a useful
recursive
definition.For example, this function would not be possible if we applied
the
"object or array" restriction:unnest(json) returns setof json
Note that a similar distinction appears with the XML type:
"document"
versus "content".I think you're playing with words. But in any case, the RFC says this
regarding generators:5. Generators
A JSON generator produces JSON text. The resulting text MUST
strictly conform to the JSON grammar.
I know it is a weak argument, but at least python, ruby and Javascript
in both Firefox and Chrome do "generate" JSON values, so our users might
kind of expect us to do the same :
Python
---------
hannu@hvost:~$ python
Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
import json
json.dumps(1)
'1'
Ruby:
-------
hannu@hvost:~$ irb
irb(main):001:0> require 'json'
=> true
irb(main):002:0> JSON.generate(1)
=> "1"
Mozilla Javascript
------------------
JSON.stringify(1) "1"
Chrome Javascript
------------------
JSON.stringify(1)
"1"
Our functions do seem to be JSON generators. So even if we accept
things that aren't JSON texts in our parser (possibly permitted
by section 4 of the RFC) we should not be generating them.
we could have a function
json_generator(json) returns text
for generating pure JSON texts ;)
the argument for interpreting out json type as "JSON value" instead of
"JSON text" would be much bigger flexibility regarding extension types
support for json (and not only extension types, but also the types
explicitly unsupported by json, like Date) via defining casts to and
from json.
-------------------------------------------------------------------------
Unsupported native data types
-----------------------------
JavaScript syntax defines several native data types not included in the
JSON standard:[7] Date, Error, Math, Regular Expression, and Function.
These JavaScript data types must be represented as some other data
format, with the programs on both ends agreeing on how to convert
between types. As of 2011, there are some de facto standards for e.g.
converting between Date and String, but none universally
recognized.[8][9] Other languages may have a different set of native
types that must be serialized carefully to deal with this type of
conversion.
-------------------------------------------------------------------------
If we allowed user-defined casts for things like Date the out users
could decide, which de facto standard to support on each specific case .
But if we did interpret out json type strictly as "JSON text", not "JSON
value", this would need another type for json_value.
And it is entirely possible that somebody does want to do what merlin
described recently, that is get a rowset of "json" values from the
client and wrap them in '[' and ']' on way out, it wuld be shame to
restrict his json array elements to be just objects and arrays and not
the other legal json values.
--
-------
Hannu Krosing
PostgreSQL Unlimited Scalability and Performance Consultant
2ndQuadrant Nordic
PG Admin Book: http://www.2ndQuadrant.com/books/
On Tue, 2012-05-01 at 09:22 -0700, Andrew Dunstan wrote:
On Tue, May 1, 2012 at 9:05 AM, Merlin Moncure <mmoncure@gmail.com>
wrote:
On Tue, May 1, 2012 at 10:49 AM, Joey Adams
<joeyadams3.14159@gmail.com> wrote:On Tue, May 1, 2012 at 8:02 AM, Hannu Krosing
<hannu@2ndquadrant.com> wrote:
Hi hackers
After playing around with array_to_json() and row_to_json()
functions a
bit it I have a question - why do we even have 2 variants
*_to_json()
Here's the discussion where that decision was made:
http://archives.postgresql.org/pgsql-hackers/2012-01/msg01339.php
To quote:
why not call all these functions 'to_json' and overload
them?
I don't honestly feel that advances clarity much. And we
might want to overload each at some stage with options that
are specific to the datum type. We have various foo_to_xml()
functions now.-1
older proposal is more consistent with xml functions
The most compelling argument I see here is the one about
options
specific to the datum type.
I don't find that to be particularly compelling at all.
to_timestamp
for example supports multiple argument versions depending on
the input
type.* If the JSON type does not yet support, say, converting
from a
number, it will be apparent from the names and types of the
functions,
rather than being a hidden surprise. On the other hand,
array_to_json
and composite_to_json already convert ANY values to JSON, so
this
doesn't matter, anyway.
I am away from base on a consulting assignment all this week, so my
connectivity and time are severely limited, and I don't have time to
respond in depth.Let me just point out two things. First, we are approaching a beta
release. The time for changing this is long since gone, IMNSHO.
First, let me start with stating that I am really happy (and a little
amazed and envious ;) ) with what the current to_json functions are
capable of.
It is already way better than what current query_to_xml could do (at
least int 9.1, may have improved since).
hannu=# select row_to_json(z) from (select 1::int as a, (select s from
(select 2::int as x, 2::text as b)s))z;
row_to_json
-----------------------------
{"a":1,"s":{"x":2,"b":"2"}}
(1 row)
hannu=# select query_to_xml('select 1::int as a, (select s from (select
2::int as x, 2::text as b)s)',true,true,'');
query_to_xml
-------------------------------------------------------------
<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">+
+
<a>1</a> +
<_x003F_column_x003F_>(2,2)</_x003F_column_x003F_> +
</row> +
+
(1 row)
The reason I am whining now is that with minor adjustments in
implementation it could all be made much more powerful (try cast
to ::json for values before cast to ::text) and much more elegant thanks
to PostgreSQL's built in casting.
If we allowed json to hold any "JSON value" and tried ::json when
generating json for compound types than we would be able to claim that
PostgreSQL supports JSON everywhere, defaulting to representing
officially unsupported types as strings, but allowing users to convert
these to their preferred conventions.
I'd also prefer to have default conversions already included for some of
our sexier types, like intervals (just a two element array) and hstore
(an object) etc.
Suddenly we would be the best match database for Web development and all
things Ajax and also have a widely used built in and adjustable
interchange format to outer world.
Second, RFC 4627 is absolutely clear: a valid JSON value can only be
an object or an array, so this thing about converting arbitrary datum
values to JSON is a fantasy.
Probably a typo on your part - valid "JSON _text_" is object or array,
valid "JSON value" can also be number, text, true, false and null
What I am arguing for is interpreting our json type as representing a
"JSON value" not "JSON text", this would enable users to adjust and
extend the generation of json values via defining casts for their
specific types - most notably Date* types but also things like hstore,
which has a natural JSON representation as "object" (a list of key:value
pairs for non-js users, a.k.a. a dictionary, hash, etc.)
If anything, we should adjust the JSON input routines to disallow
anything else, rather than start to output what is not valid JSON.
I tested python, ruby and javascript in firefox and chrome, all their
JSON generators generate 1 for standalone integer 1 and "a" for
standalone string a , and none refused to convert either to JSON.
--
-------
Hannu Krosing
PostgreSQL Scalability and Performance Consultant
2ndQuadrant Nordic
PG Admin Book: http://www.2ndQuadrant.com/books/
-----Original Message-----
From: pgsql-hackers-owner@postgresql.org [mailto:pgsql-hackers-
owner@postgresql.org] On Behalf Of Hannu Krosing
Sent: Tuesday, May 01, 2012 5:29 PMThe reason I am whining now is that with minor adjustments in
implementation it could all be made much more powerful (try cast to ::json
for values before cast to ::text) and much more elegant thanks to
PostgreSQL's built in casting.If we allowed json to hold any "JSON value" and tried ::json when generating
json for compound types than we would be able to claim that PostgreSQL
supports JSON everywhere, defaulting to representing officially unsupported
types as strings, but allowing users to convert these to their preferred
conventions.
I get that a JSON Text is always also a JSON Value but the reverse is not true. Thus, if we define JSON to be JSON Value we cannot guarantee that the encoded value is a possible JSON Text - the most important property for purposes of data interchange.
I'd also prefer to have default conversions already included for some of our
sexier types, like intervals (just a two element array) and hstore (an object)
etc.
Interval is not simply 2 values but also denotes whether the particular value is inclusive or exclusive; you would have to use an object unless you transmit in a text format and let the target perform the necessary interpretation of the string.
Suddenly we would be the best match database for Web development and
all things Ajax and also have a widely used built in and adjustable interchange
format to outer world.Second, RFC 4627 is absolutely clear: a valid JSON value can only be
an object or an array, so this thing about converting arbitrary datum
values to JSON is a fantasy.Probably a typo on your part - valid "JSON _text_" is object or array, valid
"JSON value" can also be number, text, true, false and nullWhat I am arguing for is interpreting our json type as representing a "JSON
value" not "JSON text", this would enable users to adjust and extend the
generation of json values via defining casts for their specific types - most
notably Date* types but also things like hstore, which has a natural JSON
representation as "object" (a list of key:value pairs for non-js users, a.k.a. a
dictionary, hash, etc.)
Aside from the fact it is likely too late to change the interpretation I would argue against doing so in any case.
Currently, the idea is to get your result all lined up and ready to go and then ship it off to the caller as valid JSON so that the caller does not have to do so itself. Answering the question "what would this value look like if it was part of a json output?" is good; however, production use is likely to mostly care about the entire json interchange construct (i.e., JSON Text)
So: json -> json_text;
A JSON Value always has a textual representation but if we were to have an actual type it would make sense to encode it such that (strings, objects and arrays) are delimited while (numbers, false, true, and null) are not.
Type Name: json_value
Output Representations (all output surrounded by double-quotes since all are string-like) -
String: "'VALUE'" (single-quote delimiter)
Object: "{...}"
Array: "[]"
Number: "0.00"
Other: "false", "true", "null"
JSON is fundamentally an interchange format (especially from a database's perspective). JSON Values only really have meaning if they are attached explicitly to a JSON Text structure, if you wanted to store one independently you should convert it into a native representation first. The few exceptions to this would be sufficiently handled via plain text with meta-data indicating that the stored value is structured in directly JSON compatible syntax. In short, the default context for JSON in PostgreSQL should JSON Text (not JSON Value) and thus the unadorned "json" should reflect this default (which it does).
If anything, we should adjust the JSON input routines to disallow
anything else, rather than start to output what is not valid JSON.I tested python, ruby and javascript in firefox and chrome, all their JSON
generators generate 1 for standalone integer 1 and "a" for standalone string
a , and none refused to convert either to JSON.
^Assume that we keep the meaning of json to be JSON Text; what would you suggest occurs if someone attempts a datum -> json cast? Given that we are working in a strongly-typed environment the meaning of JSON cannot be changed and so either the cast has to output valid JSON Text or it has to fail. My personal take it is have it fail since any arbitrary decision to cast to JSON Text is going to make someone unhappy and supposedly they can modify their query so that the result generates whatever format they desire.
I haven't followed the JSON development in 9.2 too closely but exposing whatever conversion mechanism is currently used to generate JSON makes sense from a ease-of-development standpoint. But even then, during development passing around true JSON Text is not a big deal and then no "JSON_Value" API has to be exposed; thus it can be freely refined, along with related behavior - e.g., append_to_json(value json_value, location text), in 9.3
So, in short, all of your ideas are still valid but use "json_value" for the data type. But, even them my guess is that you would rarely use json_value as a column type whereas you would frequently use json (JSON Text) for one. json_value would be a support type to facilitate working with json in a procedural-like way.
David J.
Andrew Dunstan <andrew@dunslane.net> writes:
On Tue, May 1, 2012 at 9:56 AM, Joey Adams <joeyadams3.14159@gmail.com>wrote:
No, the RFC says (emphasis mine):
A JSON *text* is a serialized object or array.
If we let the JSON type correspond to a *value* instead, this
restriction does not apply, and the JSON type has a useful recursive
definition.
I think you're playing with words. But in any case, the RFC says this
regarding generators:
5. Generators
A JSON generator produces JSON text. The resulting text MUST
strictly conform to the JSON grammar.
I read over the RFC, and I think the only reason why they restricted
JSON texts to represent just a subset of JSON values is this cute
little hack in section 3 (Encoding):
Since the first two characters of a JSON text will always be ASCII
characters [RFC0020], it is possible to determine whether an octet
stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
at the pattern of nulls in the first four octets.
00 00 00 xx UTF-32BE
00 xx 00 xx UTF-16BE
xx 00 00 00 UTF-32LE
xx 00 xx 00 UTF-16LE
xx xx xx xx UTF-8
They need a guaranteed 2 ASCII characters to make that work, and
they won't necessarily get that many with a bare string literal.
Since for our purposes there is not, and never will be, any need to
figure out whether a JSON input string is encoded in UTF16 or UTF32,
I find myself agreeing with the camp that says we might as well consider
that our JSON type corresponds to JSON values not JSON texts. I also
notice that json_in() seems to believe that already.
However, that doesn't mean I'm sold on the idea of getting rid of
array_to_json and row_to_json in favor of a universal "to_json()"
function. In particular, both of those have optional "pretty_bool"
arguments that don't fit nicely at all in a generic conversion
function. The meaning of that flag is very closely tied to the
input being an array or record respectively.
I'm inclined to leave these functions as they are, and consider
adding a universal "to_json(anyelement)" (with no options) later.
Because it would not have options, it would not be meant to cover
cases where there's value in formatting or conversion options;
so it wouldn't render the existing functions entirely obsolete,
nor would it mean there would be no need for other specialized
conversion functions.
regards, tom lane
On Tue, 2012-05-01 at 18:35 -0400, David Johnston wrote:
-----Original Message-----
From: pgsql-hackers-owner@postgresql.org [mailto:pgsql-hackers-
owner@postgresql.org] On Behalf Of Hannu Krosing
Sent: Tuesday, May 01, 2012 5:29 PMThe reason I am whining now is that with minor adjustments in
implementation it could all be made much more powerful (try cast to ::json
for values before cast to ::text) and much more elegant thanks to
PostgreSQL's built in casting.If we allowed json to hold any "JSON value" and tried ::json when generating
json for compound types than we would be able to claim that PostgreSQL
supports JSON everywhere, defaulting to representing officially unsupported
types as strings, but allowing users to convert these to their preferred
conventions.I get that a JSON Text is always also a JSON Value but the reverse is not true.
Thus, if we define JSON to be JSON Value we cannot guarantee that the encoded
value is a possible JSON Text - the most important property for purposes of
data interchange.
Nope, the most important property for purposes of data interchange is
that we produce something that the client expects and can understand
without too much extra work on client side.
The way to "guarantee" JSON Text is to encode objects that produce it.
I see nothing wrong with returning either a complex JSON object of
simply null if the object could not be found.
I'd also prefer to have default conversions already included for some of our
sexier types, like intervals (just a two element array) and hstore (an object)
etc.Interval is not simply 2 values but also denotes whether the particular value
is inclusive or exclusive; you would have to use an object unless you transmit
in a text format and let the target perform the necessary interpretation of
the string.
if you need that info to be passed to _your_ caller you just define a
ned cast for youtr interval-to-json which returns "object" notation.
It was meant as a sample of what could be included by having generic
json values and using json casts.
Suddenly we would be the best match database for Web development and
all things Ajax and also have a widely used built in and adjustable interchange
format to outer world.Second, RFC 4627 is absolutely clear: a valid JSON value can only be
an object or an array, so this thing about converting arbitrary datum
values to JSON is a fantasy.Probably a typo on your part - valid "JSON _text_" is object or array, valid
"JSON value" can also be number, text, true, false and nullWhat I am arguing for is interpreting our json type as representing a "JSON
value" not "JSON text", this would enable users to adjust and extend the
generation of json values via defining casts for their specific types - most
notably Date* types but also things like hstore, which has a natural JSON
representation as "object" (a list of key:value pairs for non-js users, a.k.a. a
dictionary, hash, etc.)Aside from the fact it is likely too late to change the interpretation I would argue against doing so in any case.
Currently, the idea is to get your result all lined up and ready to go and
then ship it off to the caller as valid JSON so that the caller does not
have to do so itself.
"Valid JSON" is only a small part of the equation, as I quoted before
from "JSON: The Fat-Free Alternative to XML" at
http://www.json.org/fatfree.html
"JSON has no validator. Being well-formed and valid is not the same as
being correct and relevant. Ultimately, every application is responsible
for validating its inputs."
If we produce correct JSON text for things that are converible to JSON
text then we should be free to produce JSON values for simple value,
like everybody else (that is Javascript , python, ruby, ...)
I don't think it is postgreSQL's business to start educating people
about "correct" way to do JSON serialisation when everybody else does it
the generic way.
Answering the question "what would this value look like if it was part of
a json output?" is good; however, production use is likely to mostly care
about the entire json interchange construct (i.e., JSON Text)
the "what would it look like" part is important for values that are not
covered by standard and are thus encoded as text. These need to follow
conventions outside the JSON spec proper, and thus may need to be
adjusted by the developer.
Doing it via ::json casts would be the cleanest and simplest way to deal
with it.
So: json -> json_text;
A JSON Value always has a textual representation but if we were to have an
actual type it would make sense to encode it such that (strings, objects
and arrays) are delimited while (numbers, false, true, and null) are not.
And so it is, what are you trying to say here ?
Type Name: json_value
Output Representations (all output surrounded by double-quotes since all are string-like) -
String: "'VALUE'" (single-quote delimiter)
strings are surrounded by "" not ''
Object: "{...}"
Array: "[]"
Number: "0.00"
"0.00" is a sting according to JSON spec
also, objects and arrays don't have surrounding ""
Other: "false", "true", "null"
that is not what the standard says - "false" is not the same as false
without quotes - the first is string 'false', the second one is boolean
untrue
JSON is fundamentally an interchange format (especially from a database's perspective).
JSON Values only really have meaning if they are attached explicitly to a JSON Text
structure, if you wanted to store one independently you should convert it into a
native representation first. The few exceptions to this would be sufficiently
handled via plain text with meta-data indicating that the stored value is structured
in directly JSON compatible syntax.
This is something that each developer could define for his specific app
by writing an appropriate ::json cast function for the datatype, if such
casts were honoured while doing the eoutput conversion.
There is no one standard for mosts "outside jsons scope" datatypes,
In short, the default context for JSON in
PostgreSQL should JSON Text (not JSON Value) and thus the unadorned "json" should
reflect this default (which it does).
I don't think postgreSQL has hierarchical types, so that json_text would
also be json_value, but not the other way.
I'm perfectly happy with us being flexible enough to allow people to
also generate non-standard JSON - as some of them most likely are now -
if it makes the whole system cleaner and easier to use.
I don't see why PostgreSQL's JSON should be more restrictive than most
others.
If anything, we should adjust the JSON input routines to disallow
anything else, rather than start to output what is not valid JSON.I tested python, ruby and javascript in firefox and chrome, all their JSON
generators generate 1 for standalone integer 1 and "a" for standalone string
a , and none refused to convert either to JSON.Assume that we keep the meaning of json to be JSON Text; what would you
suggest occurs if someone attempts a datum -> json cast?
I would not assume such thing ;)
Given that we are working in a strongly-typed environment the meaning of
JSON cannot be changed and so either the cast has to output valid JSON Text
or it has to fail.
Most people don't work in strongly-typed environment, and thus would
work around such restriction if they need a simple JSON value at the
other end of the interchange.
They would either do like I did and use array_to_json(array[datum]) and
then strip off the [] before shipping the JSON in the most likely case
that receiver side _wants_ to get JSON value and has been getting a JSON
value from other partners, or it may decode it as array and then use the
only element.
My personal take it is have it fail since any arbitrary decision to cast
to JSON Text is going to make someone unhappy and supposedly they can
modify their query so that the result generates whatever format they desire.
Do you actually have such an experience or is it just a wild guess ?
Would the one being "unhappy" be some developer who is actually using
JSON, or somebody whoi has only academic interest in RFCs ?
I haven't followed the JSON development in 9.2 too closely but exposing
whatever conversion mechanism is currently used to generate JSON makes
sense from a ease-of-development standpoint. But even then, during
development passing around true JSON Text is not a big deal and then
no "JSON_Value" API has to be exposed; thus it can be freely refined,
The use of casts to json would be a very natural way to make all
postgreSQL type exportable to correct JSON and would give the control
over the exact conversion details to the developer.
Currently we blindly use for json value whatever the text format of the
field happens to be with no choice other than either do the whole
conversion ourselves or then accept that some datums have unsuitable
formats and need to do some ugly and possibly error-prone conversions on
the client.
that way madness lies - I'm pretty sure I don't want to do any of that.
I want my database do the conversion for standard tyoes and give me a
choice to change the conversion for _only_ the types I need,
Using type specific casts to json give me exactly this.
along with related behavior - e.g., append_to_json(value json_value, location text), in 9.3
So, in short, all of your ideas are still valid but use "json_value"
for the data type. But, even them my guess is that you would rarely
use json_value as a column type whereas you would frequently use json
(JSON Text) for one.
json_value would be a support type to facilitate working with json in
a procedural-like way.
If you are really paranoid about somebody returning json value out of
postgresql why not just use a filter function which would fail if the
argument is not an array or text
define fail_if_not_json_text(json) returns json
this gives the developers the choice to still return JSON Values to
clients if they need.
--
-------
Hannu Krosing
PostgreSQL Unlimited Scalability and Performance Consultant
2ndQuadrant Nordic
PG Admin Book: http://www.2ndQuadrant.com/books/
On May 1, 2012, at 20:41, Hannu Krosing <hannu@2ndQuadrant.com> wrote:
Most people don't work in strongly-typed environment, and thus would
work around such restriction if they need a simple JSON value at the
other end of the interchange.My personal take it is have it fail since any arbitrary decision to cast
to JSON Text is going to make someone unhappy and supposedly they can
modify their query so that the result generates whatever format they desire.Do you actually have such an experience or is it just a wild guess ?
So even given the semantic differences between an object and a scalar I am better understanding where interpreting JSON as JSON Value makes sense. However, if I convert a record or array to JSON I expect to get a JSON Text even if the there is only a single column or value in the input.
I guess my take is that record -> JSON text while anything else is JSON value. Whether it is worth maiming the special case for record is worthwhile I really do not know but the semantic difference does exist; and record output is a significant aspect of PostgreSQL output.
I get the ease-of-use aspect but also recognize that sometimes being slightly harder to use is worthwhile if you eliminate ambiguities or limit the possibility to make mistakes.
FWIW my background on this topic is more theoretical than experiential though I am an web-application developer by trade and do use some JSON in that capacity.
David J.
On Tue, 2012-05-01 at 21:22 -0400, David Johnston wrote:
On May 1, 2012, at 20:41, Hannu Krosing <hannu@2ndQuadrant.com> wrote:
Most people don't work in strongly-typed environment, and thus would
work around such restriction if they need a simple JSON value at the
other end of the interchange.My personal take it is have it fail since any arbitrary decision to cast
to JSON Text
For arrays and records the json text and jason value are exactly the
same. it is just that json representations of simple types are
officially not JSON texts.
is going to make someone unhappy and supposedly they can
modify their query so that the result generates whatever format they desire.
Do you actually have such an experience or is it just a wild guess ?
So even given the semantic differences between an object and a scalar
I am better understanding where interpreting JSON as JSON Value makes
sense. However, if I convert a record or array to JSON I expect to get
a JSON Text even if the there is only a single column or value in the input.
Of course you will, and you will get a Json Text even for empty object
or array.
array[1] and 1 and {'one':1} are all different and will stay such.
I guess my take is that record -> JSON text while anything else is JSON
value. Whether it is worth maiming the special case for record is
worthwhile I really do not know but the semantic difference does exist;
and record output is a significant aspect of PostgreSQL output.
I have never suggested that we special-case an 1-element record or list
and start returning only the contained value for these.
I get the ease-of-use aspect but also recognize that sometimes being slightly
harder to use is worthwhile if you eliminate ambiguities or limit the
possibility to make mistakes.
There are no ambiguities in what is returnded for record or array.
But not being able to return JSON values via cast to json for some types
or not using such casts will make extending the json support for types
by user much much harder. And nonstandard.
Using simple cast to json is very PostgreSQL-ish way to give support of
json to any type
--
-------
Hannu Krosing
PostgreSQL Unlimited Scalability and Performance Consultant
2ndQuadrant Nordic
PG Admin Book: http://www.2ndQuadrant.com/books/
On Tue, 2012-05-01 at 19:11 -0400, Tom Lane wrote:
Andrew Dunstan <andrew@dunslane.net> writes:
On Tue, May 1, 2012 at 9:56 AM, Joey Adams <joeyadams3.14159@gmail.com>wrote:
No, the RFC says (emphasis mine):
A JSON *text* is a serialized object or array.
If we let the JSON type correspond to a *value* instead, this
restriction does not apply, and the JSON type has a useful recursive
definition.I think you're playing with words. But in any case, the RFC says this
regarding generators:
5. Generators
A JSON generator produces JSON text. The resulting text MUST
strictly conform to the JSON grammar.I read over the RFC, and I think the only reason why they restricted
JSON texts to represent just a subset of JSON values is this cute
little hack in section 3 (Encoding):Since the first two characters of a JSON text will always be ASCII
characters [RFC0020], it is possible to determine whether an octet
stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
at the pattern of nulls in the first four octets.
00 00 00 xx UTF-32BE
00 xx 00 xx UTF-16BE
xx 00 00 00 UTF-32LE
xx 00 xx 00 UTF-16LE
xx xx xx xx UTF-8They need a guaranteed 2 ASCII characters to make that work, and
they won't necessarily get that many with a bare string literal.Since for our purposes there is not, and never will be, any need to
figure out whether a JSON input string is encoded in UTF16 or UTF32,
I find myself agreeing with the camp that says we might as well consider
that our JSON type corresponds to JSON values not JSON texts. I also
notice that json_in() seems to believe that already.However, that doesn't mean I'm sold on the idea of getting rid of
array_to_json and row_to_json in favor of a universal "to_json()"
function. In particular, both of those have optional "pretty_bool"
arguments that don't fit nicely at all in a generic conversion
function. The meaning of that flag is very closely tied to the
input being an array or record respectively.
The flags probably should not be tied to specific type, as JSON is
recursive and as such I think the current one-top-level-element-per row
is quite limited form of pretty-printing.
I have a table with a field the type of which is an array of type of
another table, and what I currently get with pretty=true is
hannu=# select row_to_json(test3, true) from test3;
-[ RECORD
1 ]----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
row_to_json | {"id":1,
|
"data3":[{"id":1,"data2":{"id":1,"data":"0.262814193032682","tstamp":"2012-04-05 13:21:03.235204"},"tstamp":"2012-04-05 13:25:03.644497"},{"id":2,"data2":{"id":2,"data":"0.157406373415142","tstamp":"2012-04-05 13:21:05.2033"},"tstamp":"2012-04-05 13:25:03.644497"}],
| "tstamp":"2012-04-16 14:40:15.795947"}
What I would like to get what python's pprint does for the same json:
pprint(row)
{'id': 1,
'data3': [{'data2': {'data': '0.262814193032682',
'id': 1,
'tstamp': '2012-04-05 13:21:03.235204'},
'id': 1,
'tstamp': '2012-04-05 13:25:03.644497'},
{'data2': {'data': '0.157406373415142',
'id': 2,
'tstamp': '2012-04-05 13:21:05.2033'},
'id': 2,
'tstamp': '2012-04-05 13:25:03.644497'}],
'tstamp': '2012-04-16 14:40:15.795947'}
If we have a pretty flag why not make it work all the way down the
structure ?
I'm inclined to leave these functions as they are, and consider
adding a universal "to_json(anyelement)" (with no options) later.
To achieve recursive prettyprinting the better way is to have an
universal to_json(anyelement) with a prettyprinting option
to_json(datum anyelement, indent int)
with the behavior that if indent is NULL or negative integer no
pretty-printing is done, if it is 0 printing starts at left margin and
if it is a positive integer then this number of spaces is added to the
left for each row (except the first one) of the json representation.
And it would be overridable for specific types, so that hstore could
provide its own
to_json(datum hstore, indent int)
which would do the correct pretty-printing for hstor-as-json_object
representation.
Because it would not have options, it would not be meant to cover
cases where there's value in formatting or conversion options;
so it wouldn't render the existing functions entirely obsolete,
nor would it mean there would be no need for other specialized
conversion functions.
I don't object to row_to_json() and array_to_json() functions being
there as a convenience and as the two "official" functions guaranteed to
return "JSON text".
regards, tom lane
--
-------
Hannu Krosing
PostgreSQL Unlimited Scalability and Performance Consultant
2ndQuadrant Nordic
PG Admin Book: http://www.2ndQuadrant.com/books/