leer externo estructura ejemplo con json regex parsing sas

externo - json javascript ejemplo



Analizar tablas con caracteres Unicode en variables de JSON con SAS BASE (1)

Me enfrenté a un problema al analizar JSON con unicode char in vars. Entonces, tengo el próximo JSON (ejemplo):

{ "SASJSONExport":"1.0", "SASTableData+TEST":[ { "/u041f/u0435/u0440/u0435/u043c/u0435/u043d/u043d/u0430/u044f":2, "/u0421/u0440/u0435/u0434/u043d/u0435/u0435":4, "/u0421/u0442/u0440/u043e/u043a/u0430":"/u0427/u0442/u043e/u002d/u0442/u043e/u0031" }, { "/u041f/u0435/u0440/u0435/u043c/u0435/u043d/u043d/u0430/u044f":2, "/u0421/u0440/u0435/u0434/u043d/u0435/u0435":2, "/u0421/u0442/u0440/u043e/u043a/u0430":"/u0427/u0442/u043e/u002d/u0442/u043e/u0032" }, { "/u041f/u0435/u0440/u0435/u043c/u0435/u043d/u043d/u0430/u044f":1, "/u0421/u0440/u0435/u0434/u043d/u0435/u0435":42, "/u0421/u0442/u0440/u043e/u043a/u0430":"/u0427/u0442/u043e/u002d/u0442/u043e/u0033" } ] }

Para analizar la tabla desde JSON utilizo el motor SAS:

libname jsonfl JSON fileref=injson ;

El código decodifica más caracteres en las celdas, pero el nombre de los vars parece vals perdidos:

+--------------+---------------------------+------------+---------+---------+ | ordinal_root | ordinal_SASTableData_TEST | __________ | _______ | ______ | +--------------+---------------------------+------------+---------+---------+ | 1 | 1 | 2 | 4 | Что-то1 | | 1 | 2 | 2 | 2 | Что-то2 | | 1 | 3 | 1 | 42 | Что-то3 | +--------------+---------------------------+------------+---------+---------+

El encabezado debe verse así:

+--------------+---------------------------+------------+---------+---------+ | ordinal_root | ordinal_SASTableData_TEST | Переменная | Среднее | Строка | +--------------+---------------------------+------------+---------+---------+

Así que decidí reemplazar los caracteres de variables sin codificación con nombres como este DIM_N_ . Y para eso debo encontrar todas las cadenas, que concuerden con la próxima expresión regular: /([/s/w/d//]+)/"/:/

Pero, para obtener cadenas de json, necesito establecer como delim el siguiente char ''{'',''}'',''['','']'','','' . Pero si configuro esos caracteres como dlm, no ensamblaré json nuevamente. Así que decidí pegar antes del char ~ para configurarlo como dlm.

data delim; infile injson lrecl=1073741823 nopad; file delim; input char1 $char1. @@; if char1 in (''{'',''}'',''['','']'','','') then put ''7E''x; put char1 $CHAR1. @@; run;

Recibí el archivo novalid json:

~ {"SASJSONExport":"1.0"~ ,"SASTableData+TEST":~ [ ~ {"/u0056/u0061/u0072":2~ ,"/u006d/u0065/u0061/u006e":4~ ,"/u004e/u0061/u006d/u0065":"/u0073/u006d/u0074/u0068/u0031"~ }~ , ~ {"/u0056/u0061/u0072":2~ ,"/u006d/u0065/u0061/u006e":2~ ,"/u004e/u0061/u006d/u0065":"/u0073/u006d/u0074/u0068/u0032"~ }~ , ~ {"/u0056/u0061/u0072":1~ ,"/u006d/u0065/u0061/u006e":42~ ,"/u004e/u0061/u006d/u0065":"/u0073/u006d/u0074/u0068/u0033"~ } ~ ]~ }

Entonces, como paso siguiente, estoy analizando JSON y uso ~ como delimitador:

data transfer; length column $2000; retain r; infile delim delimiter=''7E''x nopad; input char1 : $4000. @@; r = prxparse(''/([/s/w/d//]+)/"/:/''); pos = prxmatch(r,char1); column = prxposn(r,1,char1); n= _n_; run;

Funciona ... Pero siento que esas son prácticas muy malas , y tiene límites.

UPD1
Opción,

options vAlidfmtname=long VALIDMEMNAME=extend VALIDVARNAME=any;

regreso:

+--------------+---------------------------+----------------------------+---------+--------------+ | ordinal_root | ordinal_SASTableData_TEST | __________ | _______ | ______ | +--------------+---------------------------+----------------------------+---------+--------------+ | 1 | 1 | авфа2 фвафв = фвыа - тфвыа | 4 | Что-то1 ,,,, | | 1 | 2 | авфа2 фвафв = фвыа - тфвыа | 2 | Что-то2 | | 1 | 3 | авфа2 фвафв = фвыа - тфвыа | 2017 | Что-то3 | +--------------+---------------------------+----------------------------+---------+--------------+

Entonces mis preguntas son:

  1. ¿Puedo decodificar todo el archivo sin la declaración de infile ?
  2. ¿Puedo usar el infile delimiter , pero establecer opciones smth para no eliminar el delimitador?

La crítica adecuada es bienvenida.


UPD
Llegué a la solución sin tener que editar manualmente el archivo de mapas json, pero usando una expresión regular.

libname _all_ clear; filename _all_ clear; filename _PDFOUT temp; filename _GSFNAME temp; proc datasets lib=work kill memtype=data nolist; quit; filename jsf ''~/sasuser.v94/.json'' encoding=''utf-8''; data _null_; file jsf; length js varchar(*); retain js; input; js=unicode(_infile_); put js; datalines; { "SASJSONExport":"1.0", "SASTableData+TEST":[ { "/u041f/u0435/u0440/u0435/u043c/u0435/u043d/u043d/u0430/u044f":2, "/u0421/u0440/u0435/u0434/u043d/u0435/u0435":4, "/u0421/u0442/u0440/u043e/u043a/u0430":"/u0427/u0442/u043e/u002d/u0442/u043e/u0031" }, { "/u041f/u0435/u0440/u0435/u043c/u0435/u043d/u043d/u0430/u044f":2, "/u0421/u0440/u0435/u0434/u043d/u0435/u0435":2, "/u0421/u0442/u0440/u043e/u043a/u0430":"/u0427/u0442/u043e/u002d/u0442/u043e/u0032" }, { "/u041f/u0435/u0440/u0435/u043c/u0435/u043d/u043d/u0430/u044f":1, "/u0421/u0440/u0435/u0434/u043d/u0435/u0435":42, "/u0421/u0442/u0440/u043e/u043a/u0430":"/u0427/u0442/u043e/u002d/u0442/u043e/u0033" } ] } ; run; filename jsm ''~/sasuser.v94/.json.map'' encoding=''utf-8''; libname jsd json fileref=jsf map=jsm automap=replace; libname jsm json fileref=jsm; data jsmm; merge jsm.datasets jsm.datasets_variables; by ordinal_DATASETS; run; proc sort data=jsmm; by ordinal_root ordinal_DATASETS; run; data _null_; set work.jsmm end=last; if _N_=1 then do; length s varchar(*) ds varchar(*); retain s ds prx; s=''{"DATASETS":[''; ds=''''; prx=prxparse(''/[^_]/''); end; if ds=dsname then s=s||'',''; else do; ds=dsname; if _N_^=1 then s=s||'']},''; s=cats(s,''{"DSNAME":"'',ds,''","TABLEPATH":"'',tablepath,''","VARIABLES":[''); end; s=cats(s,''{"NAME":"'',name,''","TYPE":"'',type,''","PATH":"'',path,''"''); if prxmatch(prx,name) > length(name) then s=cats(s,'',"LABEL":"'',scan(path,-1,''/''),''"''); s=s||''}''; if last then do; s=s||'']}]}''; file jsm; put s; end; run; libname jsd json fileref=jsf map=jsm; proc print data=jsd.SASTableData_TEST label noobs; run;

La primera variante de la solución
Es la solución rápida y sucia.
Primero preparando los datos de entrada:

libname _all_ clear; filename _all_ clear; filename jsf ''~/sasuser.v94/.json'' encoding=''utf-8''; data _null_; file jsf; length js varchar(*); input; js=unicode(_infile_); put js; datalines; { "SASJSONExport":"1.0", "SASTableData+TEST": [ { "/u041f/u0435/u0440/u0435/u043c/u0435/u043d/u043d/u0430/u044f":2, "/u0421/u0440/u0435/u0434/u043d/u0435/u0435":4, "/u0421/u0442/u0440/u043e/u043a/u0430":"/u0427/u0442/u043e/u002d/u0442/u043e/u0031" }, { "/u041f/u0435/u0440/u0435/u043c/u0435/u043d/u043d/u0430/u044f":2, "/u0421/u0440/u0435/u0434/u043d/u0435/u0435":2, "/u0421/u0442/u0440/u043e/u043a/u0430":"/u0427/u0442/u043e/u002d/u0442/u043e/u0032" }, { "/u041f/u0435/u0440/u0435/u043c/u0435/u043d/u043d/u0430/u044f":1, "/u0421/u0440/u0435/u0434/u043d/u0435/u0435":42, "/u0421/u0442/u0440/u043e/u043a/u0430":"/u0427/u0442/u043e/u002d/u0442/u043e/u0033" } ] } ; run;

El archivo de salida .json :

{ "SASJSONExport":"1.0", "SASTableData+TEST": [ { "Переменная":2, "Среднее":4, "Строка":"Что-то1" }, { "Переменная":2, "Среднее":2, "Строка":"Что-то2" }, { "Переменная":1, "Среднее":42, "Строка":"Что-то3" } ] }

Luego crea el archivo json map .json.map :

filename jsmf ''~/sasuser.v94/.json.map'' encoding=''utf-8''; libname jsm json fileref=jsf map=jsmf automap=create;

Los contenidos de .json.map :

{ "DATASETS": [ { "DSNAME": "root", "TABLEPATH": "/root", "VARIABLES": [ { "NAME": "ordinal_root", "TYPE": "ORDINAL", "PATH": "/root" }, { "NAME": "SASJSONExport", "TYPE": "CHARACTER", "PATH": "/root/SASJSONExport", "CURRENT_LENGTH": 3 } ] }, { "DSNAME": "SASTableData_TEST", "TABLEPATH": "/root/SASTableData+TEST", "VARIABLES": [ { "NAME": "ordinal_root", "TYPE": "ORDINAL", "PATH": "/root" }, { "NAME": "ordinal_SASTableData_TEST", "TYPE": "ORDINAL", "PATH": "/root/SASTableData+TEST" }, { "NAME": "____________________", "TYPE": "NUMERIC", "PATH": "/root/SASTableData+TEST/Переменная" }, { "NAME": "______________", "TYPE": "NUMERIC", "PATH": "/root/SASTableData+TEST/Среднее" }, { "NAME": "____________", "TYPE": "CHARACTER", "PATH": "/root/SASTableData+TEST/Строка", "CURRENT_LENGTH": 12 } ] } ] }

Cambiemos un poco el archivo eliminando la descripción del conjunto de datos no necesario y agregando etiquetas:

{ "DATASETS": [ { "DSNAME": "SASTableData_TEST", "TABLEPATH": "/root/SASTableData+TEST", "VARIABLES": [ { "NAME": "ordinal_root", "TYPE": "ORDINAL", "PATH": "/root" }, { "NAME": "ordinal_SASTableData_TEST", "TYPE": "ORDINAL", "PATH": "/root/SASTableData+TEST" }, { "NAME": "____________________", "TYPE": "NUMERIC", "PATH": "/root/SASTableData+TEST/Переменная", "LABEL": "Переменная" }, { "NAME": "______________", "TYPE": "NUMERIC", "PATH": "/root/SASTableData+TEST/Среднее", "LABEL": "Среднее" }, { "NAME": "____________", "TYPE": "CHARACTER", "PATH": "/root/SASTableData+TEST/Строка", "LABEL": "Строка", "CURRENT_LENGTH": 12 } ] } ] }

E intenta de nuevo:

libname jsd json fileref=jsf map=jsmf; proc print data=jsd.SASTableData_TEST label noobs; run;

El resultado:

+--------------+---------------------------+- ----------+---------+-----------+ | ordinal_root | ordinal_SASTableData_TEST | Переменная | Среднее | Строка | +--------------+---------------------------+------------+---------+-----------+ | 1 | 1 | 2 | 4 | Что-то1 | | 1 | 2 | 2 | 2 | Что-то2 | | 1 | 3 | 1 | 42 | Что-то3 | +--------------+---------------------------+------------+---------+-----------+

Todo fue hecho en SAS University Edition.