Changeset: 23712fd32936 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=23712fd32936
Modified Files:
monetdb5/modules/atoms/json_atom.c
monetdb5/modules/atoms/json_atom.h
monetdb5/modules/atoms/json_atom.mal
sql/scripts/40_json.sql
Branch: default
Log Message:
Filtering JSON components
Straightforward decomposition of a JSON string using the keys.
diffs (truncated from 310 to 300 lines):
diff --git a/monetdb5/modules/atoms/json_atom.c
b/monetdb5/modules/atoms/json_atom.c
--- a/monetdb5/modules/atoms/json_atom.c
+++ b/monetdb5/modules/atoms/json_atom.c
@@ -412,18 +412,26 @@ str JSONlength(int *ret, json *js)
throw(MAL,"json.length","Invalid JSON");
}
-//the access functions assume a valid json object
+//the access functions assume a valid json object or
+//single nested array of objects ([[[{object},..]]]
//any structure violation leads to an early abort
//The keys should be unique in an object
-str
-JSONfilterObject(json *ret, json *js, str *pat)
+static str
+JSONfilterObjectInternal(json *ret, json *js, str *pat, int flag)
{
char *namebegin,*nameend;
char *valuebegin,*valueend, *msg= MAL_SUCCEED;
char *result = NULL;
- size_t l,lim,len;
+ int l,lim,len,nesting=0;
char *j = *js;
+ skipblancs;
+ while( *j == '['){
+ nesting++;
+ j++;
+ skipblancs;
+ }
+
if ( *j != '{' )
throw(MAL,"json.filter","JSON object expected");
@@ -436,9 +444,13 @@ JSONfilterObject(json *ret, json *js, st
len = 1;
lim = BUFSIZ;
- for( j++; *j != '}'; j++){
+ for( j++; *j && *j != '}'; j++){
skipblancs;
- if (*j == '}')
+ if (*j == ']' && nesting ){
+ nesting--;
+ continue;
+ }
+ if (*j == '}' || *j ==0)
break;
if (*j != '"'){
msg = createException(MAL,"json.filter","Name
expected");
@@ -467,21 +479,30 @@ JSONfilterObject(json *ret, json *js, st
if ( l+2 > lim )
result = GDKrealloc(result, lim += BUFSIZ);
if ( strcmp("null",result) == 0){
- strncpy(result+1,"nil",3);
+ strncpy(result+len,"nil",3);
len+=3;
}else{
-
strncpy(result+1,valuebegin,valueend-valuebegin);
+
strncpy(result+len,valuebegin,valueend-valuebegin);
len += valueend-valuebegin;
}
result[len++] =',';
result[len] =0;
+ if (flag == 0)
+ goto found;
}
skipblancs;
- if (*j == '}')
- break;
+ if (*j == '}' ){
+ if(nesting ){
+ while (*j && *j != '{' && *j != ']') j++;
+ if ( *j != '{') j--;
+ }
+ continue;
+ }
+
if (*j != ',')
msg = createException(MAL,"json.filter","',' expected");
}
+found:
if ( result[1] == 0){
result[1]= ']';
result[2]= 0;
@@ -493,12 +514,24 @@ wrapup:;
}
str
+JSONfilterObject(json *ret, json *js, str *pat)
+{
+ return JSONfilterObjectInternal(ret,js,pat,0);
+}
+
+str
+JSONfilterObjectAll(json *ret, json *js, str *pat)
+{
+ return JSONfilterObjectInternal(ret,js,pat,1);
+}
+
+str
JSONfilterArray(json *ret, json *js, int *index){
char *valuebegin,*valueend, *msg= MAL_SUCCEED;
char *result = NULL, *j =*js;
- size_t l,len,lim;
- int idx = *index;
+ int l,len,lim, idx = *index;
+ skipblancs;
if ( *j != '[' )
throw(MAL,"json.filter","JSON object expected");
@@ -510,7 +543,7 @@ JSONfilterArray(json *ret, json *js, int
len = 1;
lim = BUFSIZ;
- for( j++; *j != ']'; j++){
+ for( j++; *j && *j != ']'; j++){
skipblancs;
if (*j == ']'){
break;
@@ -559,7 +592,7 @@ JSONnames(int *ret, json *js)
char *namebegin,*nameend;
char *msg= MAL_SUCCEED;
char *result = NULL;
- size_t l,lim;
+ int l,lim;
char *j = *js;
bn = BATnew(TYPE_void,TYPE_str,64);
@@ -571,6 +604,7 @@ JSONnames(int *ret, json *js)
bn->trevsorted = 0;
bn->T->nonil = 1;
+ skipblancs;
if ( *j != '{' )
throw(MAL,"json.filter","JSON object expected");
@@ -580,7 +614,7 @@ JSONnames(int *ret, json *js)
throw(MAL,"json.names",MAL_MALLOC_FAIL);
lim = BUFSIZ;
- for( j++; *j != '}'; j++){
+ for( j++; *j && *j != '}'; j++){
skipblancs;
if (*j == '}')
break;
@@ -627,8 +661,9 @@ str JSONarrayvalues(int *ret, BAT *bn, c
{
char *valuebegin,*valueend, *msg= MAL_SUCCEED;
char *result = NULL;
- size_t l,lim;
+ int l,lim;
+ skipblancs;
if ( *j != '[' )
throw(MAL,"json.value","JSON object expected");
@@ -637,7 +672,7 @@ str JSONarrayvalues(int *ret, BAT *bn, c
throw(MAL,"json.value",MAL_MALLOC_FAIL);
lim = BUFSIZ;
- for( j++; *j != ']'; j++){
+ for( j++; *j && *j != ']'; j++){
skipblancs;
if (*j == ']'){
break;
@@ -677,7 +712,7 @@ JSONvalues(int *ret, json *js)
char *valuebegin,*valueend;
char *msg= MAL_SUCCEED;
char *result = NULL;
- size_t l,lim;
+ int l,lim;
char *j = *js;
bn = BATnew(TYPE_void,TYPE_str,64);
@@ -689,6 +724,7 @@ JSONvalues(int *ret, json *js)
bn->trevsorted = 0;
bn->T->nonil = 1;
+ skipblancs;
if ( *j == '[' )
return JSONarrayvalues(ret, bn, j);
if ( *j != '{' )
@@ -700,7 +736,7 @@ JSONvalues(int *ret, json *js)
throw(MAL,"json.values",MAL_MALLOC_FAIL);
lim = BUFSIZ;
- for( j++; *j != '}'; j++){
+ for( j++; *j && *j != '}'; j++){
skipblancs;
if (*j == '}')
break;
@@ -772,7 +808,7 @@ str JSONrenderRowObject(BAT **bl, MalBlk
{
int i,tpe;
char *row,*name=0,*val=0;
- size_t len,lim,l;
+ int len,lim,l;
void *p;
BATiter bi;
@@ -789,7 +825,7 @@ str JSONrenderRowObject(BAT **bl, MalBlk
ATOMformat( tpe, p, &val);
if( strncmp(val,"nil",3) == 0)
strcpy(val,"null");
- l = strlen(name) + strlen(val);
+ l = (int)strlen(name) + (int)strlen(val);
if (l > lim-len)
row= (char*) GDKrealloc(row, lim += BUFSIZ);
snprintf(row+len,lim-len,"\"%s\":%s,", name, val);
@@ -810,8 +846,7 @@ JSONrenderobject(Client cntxt, MalBlkPtr
{
BAT **bl;
char *result, *row;
- int i;
- size_t len,lim,l;
+ int i,len,lim,l;
str *ret;
BUN j,cnt;
@@ -831,9 +866,9 @@ JSONrenderobject(Client cntxt, MalBlkPtr
for( j =0; j< cnt; j++){
row = JSONrenderRowObject(bl,mb,stk,pci,j);
- l =strlen(row);
+ l =(int)strlen(row);
if (l +2 > lim-len)
- row= (char*) GDKrealloc(row, lim = cnt * l <=
lim? cnt*l: lim+BUFSIZ);
+ row= (char*) GDKrealloc(row, lim = ((int)cnt *
l) <= lim? (int)cnt*l: lim+BUFSIZ);
strncpy(result+len,row, l+1);
GDKfree(row);
len +=l;
@@ -851,7 +886,7 @@ str JSONrenderRowArray(BAT **bl, MalBlkP
{
int i,tpe;
char *row,*val=0;
- size_t len,lim,l;
+ int len,lim,l;
void *p;
BATiter bi;
@@ -867,7 +902,7 @@ str JSONrenderRowArray(BAT **bl, MalBlkP
ATOMformat( tpe, p, &val);
if( strncmp(val,"nil",3) == 0)
strcpy(val,"null");
- l = strlen(val);
+ l = (int) strlen(val);
if (l > lim-len)
row= (char*) GDKrealloc(row, lim += BUFSIZ);
snprintf(row+len,lim-len,"%s,", val);
@@ -888,7 +923,7 @@ JSONrenderarray(Client cntxt, MalBlkPtr
{
BAT **bl;
char *result, *row;
- size_t len,lim,l;
+ int len,lim,l;
str *ret;
BUN j,cnt;
@@ -905,9 +940,9 @@ JSONrenderarray(Client cntxt, MalBlkPtr
for( j =0; j< cnt; j++){
row = JSONrenderRowArray(bl,mb,pci,j);
- l =strlen(row);
+ l = (int)strlen(row);
if (l +2 > lim-len)
- row= (char*) GDKrealloc(row, lim = cnt * l <=
lim? cnt*l: lim+BUFSIZ);
+ row= (char*) GDKrealloc(row, lim = ((int)cnt *
l) <= lim? (int)cnt*l: lim+BUFSIZ);
strncpy(result+len,row, l+1);
GDKfree(row);
len +=l;
diff --git a/monetdb5/modules/atoms/json_atom.h
b/monetdb5/modules/atoms/json_atom.h
--- a/monetdb5/modules/atoms/json_atom.h
+++ b/monetdb5/modules/atoms/json_atom.h
@@ -47,6 +47,7 @@ json_export str JSONstr2json(json *ret,
json_export str JSONjson2str(str *ret, json *j);
json_export str JSONfilterObject(json *ret, json *j, str *pat);
+json_export str JSONfilterObjectAll(json *ret, json *j, str *pat);
json_export str JSONfilterArray(json *ret, json *j, int *index);
json_export str JSONisvalid(int *ret, json *j);
diff --git a/monetdb5/modules/atoms/json_atom.mal
b/monetdb5/modules/atoms/json_atom.mal
--- a/monetdb5/modules/atoms/json_atom.mal
+++ b/monetdb5/modules/atoms/json_atom.mal
@@ -41,6 +41,10 @@ command filter(name:json, s:str) :json
address JSONfilterObject
comment "Filter the members of an object by name";
+command filterall(name:json, s:str) :json
+address JSONfilterObjectAll
+comment "Filter the members of an object by name";
+
command filter(name:json, i:int) :json
address JSONfilterArray
comment "Extract a single element from an array";
diff --git a/sql/scripts/40_json.sql b/sql/scripts/40_json.sql
--- a/sql/scripts/40_json.sql
+++ b/sql/scripts/40_json.sql
_______________________________________________
checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list