/* * stolen from * contrib/hstore/hstore_io.c */ #include "postgres.h" #include "catalog/pg_type.h" #include "funcapi.h" #include "lib/stringinfo.h" #include "utils/json.h" #include "jsonapi.h" #include "utils/builtins.h" #include "json_extra.h" #include "hstore.h" /* * hstore_to_json_loose * * This is a heuristic conversion to json which treats * 't' and 'f' as booleans and strings that look like numbers as numbers, * as long as they don't start with a leading zero followed by another digit * (think zip codes or phone numbers starting with 0). */ PG_FUNCTION_INFO_V1(hstore_to_json_loose); Datum hstore_to_json_loose(PG_FUNCTION_ARGS); Datum hstore_to_json_loose(PG_FUNCTION_ARGS) { HStore *in = PG_GETARG_HS(0); int i; int count = HS_COUNT(in); char *base = STRPTR(in); HEntry *entries = ARRPTR(in); StringInfoData tmp, dst; if (count == 0) PG_RETURN_TEXT_P(cstring_to_text_with_len("{}",2)); initStringInfo(&tmp); initStringInfo(&dst); appendStringInfoChar(&dst, '{'); for (i = 0; i < count; i++) { resetStringInfo(&tmp); appendBinaryStringInfo(&tmp, HS_KEY(entries, base, i), HS_KEYLEN(entries, i)); escape_json(&dst, tmp.data); appendStringInfoString(&dst, ": "); if (HS_VALISNULL(entries, i)) appendStringInfoString(&dst, "null"); /* guess that values of 't' or 'f' are booleans */ else if (HS_VALLEN(entries, i) == 1 && *(HS_VAL(entries, base, i)) == 't') appendStringInfoString(&dst, "true"); else if (HS_VALLEN(entries, i) == 1 && *(HS_VAL(entries, base, i)) == 'f') appendStringInfoString(&dst, "false"); else { resetStringInfo(&tmp); appendBinaryStringInfo(&tmp, HS_VAL(entries, base, i), HS_VALLEN(entries, i)); if (IsValidJsonNumber(tmp.data, tmp.len)) appendBinaryStringInfo(&dst, tmp.data, tmp.len); else escape_json(&dst, tmp.data); } if (i + 1 != count) appendStringInfoString(&dst, ", "); } appendStringInfoChar(&dst, '}'); PG_RETURN_TEXT_P(cstring_to_text(dst.data)); } PG_FUNCTION_INFO_V1(hstore_to_json); Datum hstore_to_json(PG_FUNCTION_ARGS); Datum hstore_to_json(PG_FUNCTION_ARGS) { HStore *in = PG_GETARG_HS(0); int i; int count = HS_COUNT(in); char *base = STRPTR(in); HEntry *entries = ARRPTR(in); StringInfoData tmp, dst; if (count == 0) PG_RETURN_TEXT_P(cstring_to_text_with_len("{}",2)); initStringInfo(&tmp); initStringInfo(&dst); appendStringInfoChar(&dst, '{'); for (i = 0; i < count; i++) { resetStringInfo(&tmp); appendBinaryStringInfo(&tmp, HS_KEY(entries, base, i), HS_KEYLEN(entries, i)); escape_json(&dst, tmp.data); appendStringInfoString(&dst, ": "); if (HS_VALISNULL(entries, i)) appendStringInfoString(&dst, "null"); else { resetStringInfo(&tmp); appendBinaryStringInfo(&tmp, HS_VAL(entries, base, i), HS_VALLEN(entries, i)); escape_json(&dst, tmp.data); } if (i + 1 != count) appendStringInfoString(&dst, ", "); } appendStringInfoChar(&dst, '}'); PG_RETURN_TEXT_P(cstring_to_text(dst.data)); }