Changeset: 8e3dc707bac7 for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=8e3dc707bac7 Modified Files: monetdb5/modules/atoms/json.c monetdb5/modules/atoms/json.h monetdb5/modules/atoms/json.mal Branch: default Log Message:
Add coercions to numbers A JSON value, or [value] or {"tag":value} are cast into an integer or double. Failure to parse the numbers turns them into a nil. diffs (146 lines): diff --git a/monetdb5/modules/atoms/json.c b/monetdb5/modules/atoms/json.c --- a/monetdb5/modules/atoms/json.c +++ b/monetdb5/modules/atoms/json.c @@ -354,11 +354,13 @@ JSONcompile(char *expr, pattern terms[]) terms[t].first = INT_MAX; terms[t].last = INT_MAX; if ( *s == '$'){ - if( t ) + if( t && terms[t-1].token != END_STEP) throw(MAL,"json.compile","Root node must be first"); - terms[t].token = ROOT_STEP; if ( !(*(s+1) == '.' || *(s+1) =='[' || *(s+1) == 0) ) throw(MAL,"json.compile","Root node must be first"); + s++; + if( *s == 0) + terms[t].token = ROOT_STEP; } if (*s == '.' && *(s + 1) == '.') { terms[t].token = ANY_STEP; @@ -558,10 +560,10 @@ JSONfilterInternal(json *ret, json *js, s = JSONmatch(jt, 0, terms, ++tidx); result = JSONglue(result,s,','); } - if ( s) { - l = strlen(s); - if( s[l-1] == ',') - s[l-1]=0; + if ( result) { + l = strlen(result); + if( result[l-1] == ',') + result[l-1]=0; } else l= 3; s = GDKzalloc(l+3); snprintf(s,l+3,"[%s]", (result?result:"")); @@ -922,6 +924,7 @@ JSONjson2text(str *ret, json *js) l = strlen(s); if ( l) s[l-1]= 0; *ret = s; + JSONfree(jt); return MAL_SUCCEED; } @@ -939,6 +942,71 @@ JSONjson2textSeparator(str *ret, json *j l = strlen(s); if ( l) s[l-1]= 0; *ret = s; + JSONfree(jt); + return MAL_SUCCEED; +} + +str +JSONjson2number(dbl *ret, json *js) +{ + JSON *jt; + char *rest; + + *ret = dbl_nil; + jt = JSONparse(*js,0); + switch( jt->elm[0].kind ){ + case JSON_NUMBER: + *ret = strtod(jt->elm[0].value, &rest); + if (rest && (size_t)(rest- jt->elm[0].value) != jt->elm[0].valuelen) + *ret = dbl_nil; + break; + case JSON_ARRAY: + if ( jt->free == 2){ + *ret = strtod(jt->elm[1].value, &rest); + if (rest && (size_t)(rest- jt->elm[1].value) != jt->elm[1].valuelen) + *ret = dbl_nil; + } + break; + case JSON_OBJECT: + if ( jt->free == 3){ + *ret = strtod(jt->elm[2].value, &rest); + if (rest && (size_t)(rest- jt->elm[2].value) != jt->elm[2].valuelen) + *ret = dbl_nil; + } + } + JSONfree (jt); + return MAL_SUCCEED; +} + +str +JSONjson2integer(lng *ret, json *js) +{ + JSON *jt; + char *rest; + + *ret = lng_nil; + jt = JSONparse(*js,0); + switch( jt->elm[0].kind ){ + case JSON_NUMBER: + *ret = strtol(jt->elm[0].value, &rest,0); + if (rest && (size_t)(rest- jt->elm[0].value) != jt->elm[0].valuelen) + *ret = lng_nil; + break; + case JSON_ARRAY: + if ( jt->free == 2){ + *ret = strtol(jt->elm[1].value, &rest,0); + if (rest && (size_t)(rest- jt->elm[1].value) != jt->elm[1].valuelen) + *ret = lng_nil; + } + break; + case JSON_OBJECT: + if ( jt->free == 3){ + *ret = strtol(jt->elm[2].value, &rest,0); + if (rest && (size_t)(rest- jt->elm[2].value) != jt->elm[2].valuelen) + *ret = lng_nil; + } + } + JSONfree (jt); return MAL_SUCCEED; } diff --git a/monetdb5/modules/atoms/json.h b/monetdb5/modules/atoms/json.h --- a/monetdb5/modules/atoms/json.h +++ b/monetdb5/modules/atoms/json.h @@ -75,6 +75,8 @@ json_export str JSONstr2json(json *ret, json_export str JSONjson2str(str *ret, json *j); json_export str JSONjson2text(str *ret, json *arg); json_export str JSONjson2textSeparator(str *ret, json *arg, str *sep); +json_export str JSONjson2number(dbl *ret, json *arg); +json_export str JSONjson2integer(lng *ret, json *arg); json_export str JSONfilter( json *ret, json *js, str *expr); json_export str JSONfilterArray(json *ret, json *j, int *index); diff --git a/monetdb5/modules/atoms/json.mal b/monetdb5/modules/atoms/json.mal --- a/monetdb5/modules/atoms/json.mal +++ b/monetdb5/modules/atoms/json.mal @@ -47,7 +47,15 @@ comment "Convert JSON values to their pl command text(j:json,s:str):str address JSONjson2textSeparator -comment "Convert JSON values to their plain string equivalent."; +comment "Convert JSON values to their plain string equivalent, injecting a separator."; + +command number(j:json):dbl +address JSONjson2number +comment "Convert sinple JSON values to a double, return nil upon error."; + +command integer(j:json):lng +address JSONjson2integer +comment "Convert sinple JSON values to an integer, return nil upon error."; command dump(j:json):void address JSONdump; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list