Re: JSON in 9.2 - Could we have just one to_json() function instead of two separate versions ? - Mailing list pgsql-hackers

From Hannu Krosing
Subject Re: JSON in 9.2 - Could we have just one to_json() function instead of two separate versions ?
Date
Msg-id 1336127978.19151.72.camel@hvost
Whole thread Raw
In response to JSON in 9.2 - Could we have just one to_json() function instead of two separate versions ?  (Hannu Krosing <hannu@2ndQuadrant.com>)
Responses Re: JSON in 9.2 - Could we have just one to_json() function instead of two separate versions ?
List pgsql-hackers
On Wed, 2012-05-02 at 12:06 -0700, Andrew Dunstan wrote:
> 
> 
> On Wed, May 2, 2012 at 2:29 AM, Hannu Krosing <hannu@2ndquadrant.com>
> wrote:
>         
>         
>         
>         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".
>         
> 
> So given that do we do anything about this now, or wait till 9.3?

Sorry for missing this mail, followed this only on list
I hope it is ok to CC this back to list



I'd like the json support in 9.2 updated as follows


Generic to_json(...) returning a "JSON value"
=============================================

we should have a generic to_json(...) both for eas and use and for easy
extensibility, as explained below.

to_json(...) should work for all types, returning a "json value" similar
to what current json_in does, but for all types, not just cstring.

We could keep row_to_json() and array_to_json() as official json-text
returning functions 


Configurable and extensible to_json()
======================================

When working on structured types, always the first try for getting an
element-as-json should be running to_json(element) and only if this
fails fall back to current "use text representation" code.

this enables two important things

1) configurable json-coding of values not explicitly supported by
standard

You can read about an attempt to standardise json-date formart here

http://weblogs.asp.net/bleroy/archive/2008/01/18/dates-and-json.aspx .

By allowing developers just to define their own to_json(date) function
we give them the power do decide which one to use. And if we honour
search_path when looking up the to_json() functions, then they can even
choose to have different conventions for different applications.

2) flexibility in adding support for extension types, like representing
hstore as object/dict by just providing the to_json(hstore, ...)
functions in hstore extension

Pretty-printing
===============

If we were to support prettyprinting of anything more complex than
single level structs (record or array), then we need to pass "ident"
into the to_json() function

my recommendation would be to have the signature 

to_json(datum any, ident int)

with ident = NULL meaning no prettyprint , ident =0 meaninf top level,
or "starting at left margin" and anything else meaning the amount of
spaces needed to be added to the beginning of all rows exept the first
one, for example the query 

hannu=# select array_to_json(array(select test from test limit 2),true);                           array_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"}]
 
(1 row)

could return this:

[{'data': 'testdata', 'id': 9, 'tstamp': '2012-05-01 09:44:50.175189'},{'data': 'testdata', 'id': 10, 'tstamp':
'2012-05-0109:45:50.260276'}]
 

if it would call to_json(row, 1) for getting each row prettyprinted with
ident 1


Getting a record _from_ json()
==============================

JSON support would be much more useful if we supported the function of
converting the other way as well, that is from json to record

The best model easy to support seems to be what Merlin suggested, that
is the populate_record(record,hstore) function and corresponding #=
operator (see: http://www.postgresql.org/docs/9.1/static/hstore.html)



The complete plan for 9.2 once more
===================================

What is needed to nicely round up a  simple and powerful json type is

1. the "json" TYPE
  an agreement tha json type represents a "JSON value" (this is what   json_in currently does)


2. json output

2.1 doing the right thing with internal values
  to_json() function for converting to this "JSON value" for any type.  default implementation for 'non-json' types
returnstheir   postgresql textual representation in double quotes    (date -> "2012-05-01 09:45:50.260276"
 
  structured types use to_json() for getting values internally,   so that by defining to_json(hstore) you can
automaticallyget   hstore represented in javascript object or dictionary representation
 
  hannu=# select row_to_json(r)           from (select 1::int id, '"foo"=>1, "bar"=>"baz"'::hstore)r;
  should not return this:
                       row_to_json                        ------------------------------------------------------
{"id":1,"hstore":"\"bar\"=>\"baz\",\"foo\"=>\"1\""}  (1 row)
 
  but this                       row_to_json
------------------------------------------------------  {"id":1,"hstore":{"bar": "baz", "foo":"1"}}  (1 row)
 

2.1 getting the pretty-printing right for structured types 
  to_json(any, indent) functions for getting recursive prettyprinting.  we might also need another argument telling the
"pagewidth" we want  to pretty print to.
 


3. json input for records and arrays

3.1 json row to record
  a function to convert from json to record, so that we can use json  also as input format. modeled after
populate_record(record,hstore) from http://www.postgresql.org/docs/9.1/static/hstore.html 
 
  one json_to_row should be enough, as we can use

3.2 json array to json rows 
  if we also want to use input arrays , say send all invoice rows as   a json array, we could add a
unnest_json(json_array_of_rowsjson) returns table(json_row json)    function and then do the inputting as
 
  insert into invoice_row   select json_to_row(null::invoice_row, json_row)  from (select json_row as
unnest_json(json_array_of_rows))s;
 


> cheers
> 
> andrew

-- 
-------
Hannu Krosing
PostgreSQL Unlimited Scalability and Performance Consultant
2ndQuadrant Nordic
PG Admin Book: http://www.2ndQuadrant.com/books/



pgsql-hackers by date:

Previous
From: Simon Riggs
Date:
Subject: Re: index-only scans vs. Hot Standby, round two
Next
From: Hannu Krosing
Date:
Subject: Re: Future In-Core Replication