program insheetjson version 11.0 mata: if (findexternal("libjson()")) {} else printf("{err: Error: The required JSON library (libjson) seems to be missing so this command will fail. Read the help file for more information.}\n"); mata: if (libjson::checkVersion((1,0,2))) {} else printf("{err: The JSON library version is not compatible with this command and so will likely fail. Please update libjson.}\n"); syntax [varlist] using/ , [COLumns(string)] [TABLEselector(string)] [LIMIT(integer 0)] [OFFSET(integer 0)] [PRINTonly] [REPlace] [DEBUG] [SAVECONtents(string)] [SHOWresponse] [FOLLOWurl(string)] [FLATTEN] [TOPscalars] [aoa(integer 0)] if ( "`showresponse'" != "" ) { mata: dummy=injson_sheet("`using'", "", "","", 0, 0, 0, 0,strlen( "`debug'"), "`savecontents'" ,"",1,strlen( "`flatten'"),strlen( "`topscalars'" ),0); } else { mata: dummy=injson_sheet("`using'", "`columns'", "`varlist'","`tableselector'", strtoreal("`limit'"), strtoreal("`offset'"), strlen("`printonly'"), strlen( "`replace'"),strlen( "`debug'"), "`savecontents'" ,st_local("followurl"), 0,0,strlen("`topscalars'"),strtoreal("`aoa'")); } end mata string matrix getTable(pointer (class libjson scalar) scalar root, string rowvector cn, string rowvector selector, real scalar debugf, real scalar aoaf, real scalar aoa) { pointer (class libjson scalar) scalar tableroot pointer (class libjson scalar) scalar rownod pointer (class libjson scalar) scalar cell string matrix res if (root) {} else return(J(0,0,"")); if (cols(selector)==0) tableroot = root->getNode(""); else tableroot = root->getNode(selector); if (tableroot) {} else { printf("{err: Unable to find data. Bad result selector '%s'?}\n", selector); return(J(0,0,"")); } pointer (string rowvector) scalar colsel NC = cols(cn) colsel=J(1,NC,NULL) for (k=1; k<=NC; k++) colsel[k] = & (libjson::parseSelector(cn[k])); if ((tableroot) && (tableroot->isObject())) { if (debugf) printf("DEBUG: Single object found\n"); NR= 1; res = J(NR,NC,"") rownod = tableroot; for(c=1; c<=NC; c++) { cell = rownod->getNode(*colsel[c]); if (cell) {} else cell = rownod->getNode((*colsel[c])[1]); if (cell) { if (cell->isString()) res[1,c] = cell->getString("",""); else if (cell->isArray()) res[1,c] = cell->bracketArrayScalarValues(); } else { printf("{err: Invalid column name/selector '%s'. (Possible name candidates are: %s)}\n", cn[c], rownod->listAttributeNames(1)); return(J(0,0,"")) } } return(res); } else if ((tableroot) && (tableroot->isArray())) { NR= tableroot->arrayLength(); res = J(NR,NC,"") if (debugf) printf("DEBUG: [%f,%f] Array found\n",NR,NC); if (NR<1) return(J(0,0,"")); rownod = tableroot->getArrayValue(1) if ( rownod->isObject() || (aoaf && rownod->isArray()) ) { if (debugf) { if (rownod->isArray()) printf("DEBUG: Array of Arrays found\n"); else printf("DEBUG: Array of objects found\n"); } /* assume array of objects */ for (r=1; r<=NR; r++) { rownod = tableroot->getArrayValue(r); if (debugf) rownod->prettyPrint(); for(c=1; c<=NC; c++) { cell = rownod->getNode(*colsel[c]); if (cell) {} else cell = rownod->getNode((*colsel[c])[1]); if (cell) { if (cell->isString()) res[r,c] = cell->getString("",""); else if (cell->isArray()) res[r,c] = cell->bracketArrayScalarValues(); } else { printf("{err: Invalid column name/selector '%s'. (Possible name candidates are: %s)}\n", cn[c], rownod->listAttributeNames(1)); return(J(0,0,"")) } } } } else { if (!aoaf) printf("{err: Warning: Sheet appears to be an Array-of-Arrays, but option aoa() was not specified. This will cause your column selectors to silently fail.}\n"); } if (aoa>0) { if ((aoa+1)<=rows(res) ) { res=res[(aoa+1)..rows(res),.]; } else { printf ("{err: Warning: Too many aoa() header rows specified for the number of results returned, causing all rows to be skipped.!?!}\n"); return(J(0,0,"")); /* bad format */ } } return(res); } else { if((tableroot) && (tableroot->isString() || tableroot->isScalar()) ) { if (debugf) printf("DEBUG: Single scalar found\n"); return(J(1,1,root->getString(selector,""))); /*single scalar result*/ } return(J(0,0,"")); /* bad format */ } } void saveToFile(string scalar outputname, string scalar contents) { fh_out = fopen(outputname, "w") fput(fh_out, contents) fclose(fh_out) } string scalar followonurl(string scalar original_url, string scalar next_url) { if (strlower(substr(next_url, 1,5))=="http://") return("") /* safety feature. should be a relative url */ question_mark = strpos(next_url,"?"); if (question_mark==1) { /* some quick splicing */ qm = strpos(original_url,"?") new_url = substr(original_url,1,qm-1)+next_url } else { new_url = next_url; } printf("{txt: Following url '%s' for more table rows.}\n",new_url); displayflush(); return(new_url) } real scalar injson_sheet(string scalar url, string scalar colnames, string scalar varnames, string scalar selector, real scalar limit, real scalar offset, real scalar printonlyf, real scalar overwritef, real scalar debugf, string scalar savetofile, string scalar followurl, real scalar showresf, real scalar flattenf, real scalar topscalarsf, real scalar aoa) { class libjson scalar w pointer (class libjson scalar) scalar root string matrix tbl sel = tokens(selector); c=libjson::getrawcontents(url ,J(0,0,"")); if (debugf>0) { printf ("DEBUG: Version 1.2\n"); printf("{phang}URL returned:\n %s {p_end}\n", c); } if (strlen(savetofile)>0) { saveToFile(savetofile,c); printf("{res: URL contents saved to '%s'}\n", savetofile); } root = w.parse(c); if (root==NULL) { printf("{err: Warning: No response from source?!?}\n"); return(-1); } if (showresf>0) { printf("Response from server:\n"); if (flattenf) { fv=root->flattenToKV() for (k=1; k<=rows(fv); k++) { printf("\t%s = %s\n",fv[k,1],fv[k,2]); } } else { root->prettyPrint(); } return(0); } aoaf=aoa!=0; aoa_orig = aoa; if (aoa<=0) aoa=0; if (topscalarsf>0 && !aoaf) { pointer (class libjson scalar) scalar cell st_rclear(); root_attr = root->listAttributeNames(0); for (k=1; k<=cols(root_attr); k++) { kk= root_attr[k]; cell=root->getAttribute(kk); if (cell->isArray()) { if (cell->arrayLength()>0) { v=cell->getArrayValue(1)->getAttributeScalar(kk,"") } else v=""; } else v=root->getAttributeScalar(kk,"") if (v!=.) { if (strpos(kk," ")==0) { if (debugf>0) printf("TOPSCALARS: %s = '%s'\n",kk,v); st_global("r("+kk+")",v); } } } } fu = tokens(followurl) if (cols(fu)>0) { followurl =fu[1] pagelimit=10 if (cols(fu)>1) { pagelimit=strtoreal(fu[2]); /* max number of follows */ if (pagelimit>1) pagelimit++; /* Max number of pages */ } } cn=tokens(colnames) tbl = getTable(root, cn, sel,debugf,aoaf,aoa); if (topscalarsf>0 && aoa_orig==-1) { if (rows(tbl)>=2) for (k=1; k<= cols(tbl); k++) { kk = tbl[1,k]; v = tbl[2,k]; if (v!=.) { if (strpos(kk," ")==0) { if (debugf>0) printf("TOPSCALARS: %s = '%s'\n",kk,v); st_global("r("+kk+")",v); } } } return(0); } else { if (topscalarsf>0 && aoa>0) { printf("{err: Warning: Sheet appears to be an Array-of-Arrays, and the topscalars option only works with aoa(-1). Topscalars option ignored.}\n"); } } page_count=1 if ((rows(tbl)>0) && (strlen(followurl)>0)) { printf("Received page 1 with %f rows and %f columns\n", rows(tbl), cols(tbl)); fsel = libjson::parseSelector(followurl) url2=followonurl(url, root->getString(fsel,"")); if ( (strlen(url2)>0) && ((page_count <=pagelimit) || (pagelimit<=0)) ) { root = libjson::webcall(url2,"") page_count++ while ((root)&&(strlen(url2)>0) && ((rows(tbl)<=limit) || (limit<=0)) && ((page_count <=pagelimit) || (pagelimit<=0)) ){ tbl2 = getTable(root, cn, sel, 0) if (rows(tbl2)<=0) break; else printf("Received page %f with %f rows and %f columns\n", page_count, rows(tbl2), cols(tbl2)); tbl = tbl \ tbl2 url2=followonurl(url, root->getString(fsel,"")); page_count++ root = libjson::webcall(url2,"") } } printf("Total received: %f rows and %f columns\n", rows(tbl), cols(tbl)); } vnam = tokens(varnames); if (rows(tbl)<=0) { printf("{res: Empty result returned; Nothing to do.}\n"); return(0); } if (limit>0 && (rows(tbl)>=limit)) { tbl=tbl[1..limit,.] printf("{txt: Results were trimmed to %f observations.}\n",limit); } if (printonlyf>0) { cn tbl return(0); } current_obs = st_nobs(); start_index = 1+offset; end_index = start_index+rows(tbl)-1; end_window = end_index if (end_window> current_obs) end_window= current_obs real colvector rvec if (end_window