Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc80b992

Browse files
committed
Transform or iterate over json(b) string values
Dmitry Dolgov, reviewed and lightly edited by me.
1 parent156d388 commitc80b992

File tree

2 files changed

+252
-0
lines changed

2 files changed

+252
-0
lines changed

‎src/backend/utils/adt/jsonfuncs.c

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,25 @@ typedef struct OkeysState
5252
intsent_count;
5353
}OkeysState;
5454

55+
/* state for iterate_json_string_values function */
56+
typedefstructIterateJsonStringValuesState
57+
{
58+
JsonLexContext*lex;
59+
JsonIterateStringValuesActionaction;/* an action that will be applied
60+
to each json value */
61+
void*action_state;/* any necessary context for iteration */
62+
}IterateJsonStringValuesState;
63+
64+
/* state for transform_json_string_values function */
65+
typedefstructTransformJsonStringValuesState
66+
{
67+
JsonLexContext*lex;
68+
StringInfostrval;/* resulting json */
69+
JsonTransformStringValuesActionaction;/* an action that will be applied
70+
to each json value */
71+
void*action_state;/* any necessary context for transformation */
72+
}TransformJsonStringValuesState;
73+
5574
/* state for json_get* functions */
5675
typedefstructGetState
5776
{
@@ -271,6 +290,18 @@ static void setPathArray(JsonbIterator **it, Datum *path_elems,
271290
intlevel,Jsonb*newval,uint32nelems,intop_type);
272291
staticvoidaddJsonbToParseState(JsonbParseState**jbps,Jsonb*jb);
273292

293+
/* function supporting iterate_json_string_values */
294+
staticvoiditerate_string_values_scalar(void*state,char*token,JsonTokenTypetokentype);
295+
296+
/* functions supporting transform_json_string_values */
297+
staticvoidtransform_string_values_object_start(void*state);
298+
staticvoidtransform_string_values_object_end(void*state);
299+
staticvoidtransform_string_values_array_start(void*state);
300+
staticvoidtransform_string_values_array_end(void*state);
301+
staticvoidtransform_string_values_object_field_start(void*state,char*fname,boolisnull);
302+
staticvoidtransform_string_values_array_element_start(void*state,boolisnull);
303+
staticvoidtransform_string_values_scalar(void*state,char*token,JsonTokenTypetokentype);
304+
274305

275306
/*
276307
* SQL function json_object_keys
@@ -4130,3 +4161,208 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
41304161
}
41314162
}
41324163
}
4164+
4165+
/*
4166+
* Iterate over jsonb string values or elements, and pass them together with an
4167+
* iteration state to a specified JsonIterateStringValuesAction.
4168+
*/
4169+
void
4170+
iterate_jsonb_string_values(Jsonb*jb,void*state,JsonIterateStringValuesActionaction)
4171+
{
4172+
JsonbIterator*it;
4173+
JsonbValuev;
4174+
JsonbIteratorTokentype;
4175+
4176+
it=JsonbIteratorInit(&jb->root);
4177+
4178+
while ((type=JsonbIteratorNext(&it,&v, false))!=WJB_DONE)
4179+
{
4180+
if ((type==WJB_VALUE||type==WJB_ELEM)&&v.type==jbvString)
4181+
{
4182+
action(state,v.val.string.val,v.val.string.len);
4183+
}
4184+
}
4185+
}
4186+
4187+
/*
4188+
* Iterate over json string values or elements, and pass them together with an
4189+
* iteration state to a specified JsonIterateStringValuesAction.
4190+
*/
4191+
void
4192+
iterate_json_string_values(text*json,void*action_state,JsonIterateStringValuesActionaction)
4193+
{
4194+
JsonLexContext*lex=makeJsonLexContext(json, true);
4195+
JsonSemAction*sem=palloc0(sizeof(JsonSemAction));
4196+
IterateJsonStringValuesState*state=palloc0(sizeof(IterateJsonStringValuesState));
4197+
4198+
state->lex=lex;
4199+
state->action=action;
4200+
state->action_state=action_state;
4201+
4202+
sem->semstate= (void*)state;
4203+
sem->scalar=iterate_string_values_scalar;
4204+
4205+
pg_parse_json(lex,sem);
4206+
}
4207+
4208+
/*
4209+
* An auxiliary function for iterate_json_string_values to invoke a specified
4210+
* JsonIterateStringValuesAction.
4211+
*/
4212+
staticvoid
4213+
iterate_string_values_scalar(void*state,char*token,JsonTokenTypetokentype)
4214+
{
4215+
IterateJsonStringValuesState*_state= (IterateJsonStringValuesState*)state;
4216+
if (tokentype==JSON_TOKEN_STRING)
4217+
(*_state->action) (_state->action_state,token,strlen(token));
4218+
}
4219+
4220+
/*
4221+
* Iterate over a jsonb, and apply a specified JsonTransformStringValuesAction
4222+
* to every string value or element. Any necessary context for a
4223+
* JsonTransformStringValuesAction can be passed in the action_state variable.
4224+
* Function returns a copy of an original jsonb object with transformed values.
4225+
*/
4226+
Jsonb*
4227+
transform_jsonb_string_values(Jsonb*jsonb,void*action_state,
4228+
JsonTransformStringValuesActiontransform_action)
4229+
{
4230+
JsonbIterator*it;
4231+
JsonbValuev,*res=NULL;
4232+
JsonbIteratorTokentype;
4233+
JsonbParseState*st=NULL;
4234+
text*out;
4235+
boolis_scalar= false;
4236+
4237+
it=JsonbIteratorInit(&jsonb->root);
4238+
is_scalar=it->isScalar;
4239+
4240+
while ((type=JsonbIteratorNext(&it,&v, false))!=WJB_DONE)
4241+
{
4242+
if ((type==WJB_VALUE||type==WJB_ELEM)&&v.type==jbvString)
4243+
{
4244+
out=transform_action(action_state,v.val.string.val,v.val.string.len);
4245+
v.val.string.val=VARDATA_ANY(out);
4246+
v.val.string.len=VARSIZE_ANY_EXHDR(out);
4247+
res=pushJsonbValue(&st,type,type<WJB_BEGIN_ARRAY ?&v :NULL);
4248+
}
4249+
else
4250+
{
4251+
res=pushJsonbValue(&st,type, (type==WJB_KEY||
4252+
type==WJB_VALUE||
4253+
type==WJB_ELEM) ?&v :NULL);
4254+
}
4255+
}
4256+
4257+
if (res->type==jbvArray)
4258+
res->val.array.rawScalar=is_scalar;
4259+
4260+
returnJsonbValueToJsonb(res);
4261+
}
4262+
4263+
/*
4264+
* Iterate over a json, and apply a specified JsonTransformStringValuesAction
4265+
* to every string value or element. Any necessary context for a
4266+
* JsonTransformStringValuesAction can be passed in the action_state variable.
4267+
* Function returns a StringInfo, which is a copy of an original json with
4268+
* transformed values.
4269+
*/
4270+
text*
4271+
transform_json_string_values(text*json,void*action_state,
4272+
JsonTransformStringValuesActiontransform_action)
4273+
{
4274+
JsonLexContext*lex=makeJsonLexContext(json, true);
4275+
JsonSemAction*sem=palloc0(sizeof(JsonSemAction));
4276+
TransformJsonStringValuesState*state=palloc0(sizeof(TransformJsonStringValuesState));
4277+
4278+
state->lex=lex;
4279+
state->strval=makeStringInfo();
4280+
state->action=transform_action;
4281+
state->action_state=action_state;
4282+
4283+
sem->semstate= (void*)state;
4284+
sem->scalar=transform_string_values_scalar;
4285+
sem->object_start=transform_string_values_object_start;
4286+
sem->object_end=transform_string_values_object_end;
4287+
sem->array_start=transform_string_values_array_start;
4288+
sem->array_end=transform_string_values_array_end;
4289+
sem->scalar=transform_string_values_scalar;
4290+
sem->array_element_start=transform_string_values_array_element_start;
4291+
sem->object_field_start=transform_string_values_object_field_start;
4292+
4293+
pg_parse_json(lex,sem);
4294+
4295+
returncstring_to_text_with_len(state->strval->data,state->strval->len);
4296+
}
4297+
4298+
/*
4299+
* Set of auxiliary functions for transform_json_string_values to invoke a
4300+
* specified JsonTransformStringValuesAction for all values and left everything
4301+
* else untouched.
4302+
*/
4303+
staticvoid
4304+
transform_string_values_object_start(void*state)
4305+
{
4306+
TransformJsonStringValuesState*_state= (TransformJsonStringValuesState*)state;
4307+
appendStringInfoCharMacro(_state->strval,'{');
4308+
}
4309+
4310+
staticvoid
4311+
transform_string_values_object_end(void*state)
4312+
{
4313+
TransformJsonStringValuesState*_state= (TransformJsonStringValuesState*)state;
4314+
appendStringInfoCharMacro(_state->strval,'}');
4315+
}
4316+
4317+
staticvoid
4318+
transform_string_values_array_start(void*state)
4319+
{
4320+
TransformJsonStringValuesState*_state= (TransformJsonStringValuesState*)state;
4321+
appendStringInfoCharMacro(_state->strval,'[');
4322+
}
4323+
4324+
staticvoid
4325+
transform_string_values_array_end(void*state)
4326+
{
4327+
TransformJsonStringValuesState*_state= (TransformJsonStringValuesState*)state;
4328+
appendStringInfoCharMacro(_state->strval,']');
4329+
}
4330+
4331+
staticvoid
4332+
transform_string_values_object_field_start(void*state,char*fname,boolisnull)
4333+
{
4334+
TransformJsonStringValuesState*_state= (TransformJsonStringValuesState*)state;
4335+
4336+
if (_state->strval->data[_state->strval->len-1]!='{')
4337+
appendStringInfoCharMacro(_state->strval,',');
4338+
4339+
/*
4340+
* Unfortunately we don't have the quoted and escaped string any more, so
4341+
* we have to re-escape it.
4342+
*/
4343+
escape_json(_state->strval,fname);
4344+
appendStringInfoCharMacro(_state->strval,':');
4345+
}
4346+
4347+
staticvoid
4348+
transform_string_values_array_element_start(void*state,boolisnull)
4349+
{
4350+
TransformJsonStringValuesState*_state= (TransformJsonStringValuesState*)state;
4351+
4352+
if (_state->strval->data[_state->strval->len-1]!='[')
4353+
appendStringInfoCharMacro(_state->strval,',');
4354+
}
4355+
4356+
staticvoid
4357+
transform_string_values_scalar(void*state,char*token,JsonTokenTypetokentype)
4358+
{
4359+
TransformJsonStringValuesState*_state= (TransformJsonStringValuesState*)state;
4360+
4361+
if (tokentype==JSON_TOKEN_STRING)
4362+
{
4363+
text*out= (*_state->action) (_state->action_state,token,strlen(token));
4364+
escape_json(_state->strval,text_to_cstring(out));
4365+
}
4366+
else
4367+
appendStringInfoString(_state->strval,token);
4368+
}

‎src/include/utils/jsonapi.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#ifndefJSONAPI_H
1515
#defineJSONAPI_H
1616

17+
#include"jsonb.h"
1718
#include"lib/stringinfo.h"
1819

1920
typedefenum
@@ -131,4 +132,19 @@ extern JsonLexContext *makeJsonLexContextCstringLen(char *json,
131132
*/
132133
externboolIsValidJsonNumber(constchar*str,intlen);
133134

135+
/* an action that will be applied to each value in iterate_json(b)_string_vaues functions */
136+
typedefvoid (*JsonIterateStringValuesAction) (void*state,char*elem_value,intelem_len);
137+
138+
/* an action that will be applied to each value in transform_json(b)_string_values functions */
139+
typedeftext* (*JsonTransformStringValuesAction) (void*state,char*elem_value,intelem_len);
140+
141+
externvoiditerate_jsonb_string_values(Jsonb*jb,void*state,
142+
JsonIterateStringValuesActionaction);
143+
externvoiditerate_json_string_values(text*json,void*action_state,
144+
JsonIterateStringValuesActionaction);
145+
externJsonb*transform_jsonb_string_values(Jsonb*jsonb,void*action_state,
146+
JsonTransformStringValuesActiontransform_action);
147+
externtext*transform_json_string_values(text*json,void*action_state,
148+
JsonTransformStringValuesActiontransform_action);
149+
134150
#endif/* JSONAPI_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp