Re: new json funcs

From: Andrew Dunstan <andrew(at)dunslane(dot)net>
To: Alvaro Herrera <alvherre(at)2ndquadrant(dot)com>
Cc: Josh Berkus <josh(at)agliodbs(dot)com>, pgsql-hackers(at)postgresql(dot)org
Subject: Re: new json funcs
Date: 2014-01-28 20:51:44
Message-ID: 52E81860.1040203@dunslane.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers


On 01/28/2014 01:22 PM, Alvaro Herrera wrote:
> Josh Berkus wrote:
>> On 01/27/2014 01:06 PM, Alvaro Herrera wrote:
>>> Andrew Dunstan escribió:
>>>
>>>> I'm not sure I understand the need. This is the difference between
>>>> the _text variants and their parents. Why would you call
>>>> json_object_field when you want the dequoted text?
>>> Because I first need to know its type. Sometimes it's an array, or an
>>> object, or a boolean, and for those I won't call the _text version
>>> afterwards but just use the original.
>> It would make more sense to extract them as JSON, check the type, and
>> convert.
> That's what I'm already doing. My question is how do I convert it?
> I have this, but would like to get rid of it:
>
> /*
> * dequote_jsonval
> * Take a string value extracted from a JSON object, and return a copy of it
> * with the quoting removed.
> *
> * Another alternative to this would be to run the extraction routine again,
> * using the "_text" variant which returns the value without quotes; but this
> * complicates the logic a lot because not all values are extracted in
> * the same way (some are extracted using json_object_field, others
> * using json_array_element). Dequoting the object already at hand is a
> * lot easier.
> */
> static char *
> dequote_jsonval(char *jsonval)
> {
> char *result;
> int inputlen = strlen(jsonval);
> int i;
> int j = 0;
>
> result = palloc(strlen(jsonval) + 1);
>
> /* skip the start and end quotes right away */
> for (i = 1; i < inputlen - 1; i++)
> {
> /*
> * XXX this skips the \ in a \" sequence but leaves other escaped
> * sequences in place. Are there other cases we need to handle
> * specially?
> */
> if (jsonval[i] == '\\' &&
> jsonval[i + 1] == '"')
> {
> i++;
> continue;
> }
>
> result[j++] = jsonval[i];
> }
> result[j] = '\0';
>
> return result;
> }
>

Well, TIMTOWTDI. Here's roughly what I would do, in json.c, making the
json lexer do the work for us:

extern char *
dequote_scalar_json_string(char *jsonval)
{
text *json = cstring_to_text(jsonval);
JsonLexContext *lex = makeJsonLexContext(json, true);
JsonTokenType tok;
char *ret;

json_lex(lex);
tok = lex_peek(lex);
if (tok == JSON_TOKEN_STRING)
ret=pstrdup(lex->strval->data);
else
ret = jsonval;
pfree(lex->strval->data);
pfree(lex->strval);
pfree(lex);
pfree(json);

return ret;
}

I'm not sure if we should have a gadget like this at the SQL level also.

cheers

andrew

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Bruce Momjian 2014-01-28 21:11:54 Re: fixing pg_ctl with relative paths
Previous Message Tom Lane 2014-01-28 20:39:07 Re: Planning time in explain/explain analyze