in src/collection_parse.c [60:171]
static JsonParseErrorType json_collection_object_field_start(void *state,
char *fname,
bool isnull);
static JsonParseErrorType json_collection_scalar(void *state,
char *token,
JsonTokenType tokentype);
CollectionHeader *
parse_collection(char *json)
{
CollectionHeader *colhdr;
MemoryContext oldcxt;
ListCell *lc1;
ListCell *lc2;
Oid typInput;
Oid typIOParam;
int i = 0;
JsonParseErrorType json_error;
JsonSemAction sem;
JsonCollectionParseState parse;
JsonCollectionParseContext context;
colhdr = construct_empty_collection(CurrentMemoryContext);
oldcxt = MemoryContextSwitchTo(colhdr->hdr.eoh_context);
context.private_data = json;
parse.context = &context;
parse.state = EXPECT_TOPLEVEL_START;
#if (PG_VERSION_NUM >= 170000)
parse.lex = makeJsonLexContextCstringLen(NULL, json, strlen(json), PG_UTF8, true);
#else
parse.lex = makeJsonLexContextCstringLen(json, strlen(json), PG_UTF8, true);
#endif
parse.keys = NIL;
parse.values = NIL;
parse.typname = NULL;
/* Set up semantic actions. */
sem.semstate = &parse;
#if (PG_VERSION_NUM >= 160000)
sem.object_start = json_collection_object_start;
sem.object_end = json_collection_object_end;
sem.array_start = json_collection_array_start;
sem.object_field_start = json_collection_object_field_start;
sem.scalar = json_collection_scalar;
#else
/* Quiet the compiler */
sem.object_start = (void *) json_collection_object_start;
sem.object_end = (void *) json_collection_object_end;
sem.array_start = (void *) json_collection_array_start;
sem.object_field_start = (void *) json_collection_object_field_start;
sem.scalar = (void *) json_collection_scalar;
#endif
sem.array_end = NULL;
sem.object_field_end = NULL;
sem.array_element_start = NULL;
sem.array_element_end = NULL;
json_error = pg_parse_json(parse.lex, &sem);
if (json_error != JSON_SUCCESS)
elog(ERROR, "Invalid format");
if (parse.typname)
{
Oid typid;
typid = DatumGetObjectId(DirectFunctionCall1(regtypein, CStringGetDatum(parse.typname)));
colhdr->value_type = typid;
colhdr->value_type_len = get_typlen(typid);
colhdr->value_byval = get_typbyval(typid);
}
else
{
colhdr->value_type = TEXTOID;
colhdr->value_type_len = -1;
colhdr->value_byval = false;
}
getTypeInputInfo(colhdr->value_type, &typInput, &typIOParam);
forboth(lc1, parse.keys, lc2, parse.values)
{
collection *item;
char *key = lfirst(lc1);
char *vstr = lfirst(lc2);
Datum value;
item = (collection *) palloc(sizeof(collection));
item->key = key;
value = OidFunctionCall1(typInput, CStringGetDatum(vstr));
item->value = datumCopy(value, colhdr->value_byval, colhdr->value_type_len);
HASH_ADD_KEYPTR(hh, colhdr->current, key, strlen(key), item);
if (i == 0)
colhdr->head = colhdr->current;
i++;
}
colhdr->current = colhdr->head;
MemoryContextSwitchTo(oldcxt);
return colhdr;
}