JSON a Cursor, pero rápido

432 views
Skip to first unread message

Cristian Novoa

unread,
Feb 13, 2024, 2:20:55 PM2/13/24
to Comunidad de Visual Foxpro en Español
Hola estimados,

Estoy tratando de convertir un json a cursor, pero debe demorar segundos, y tanto la solución de V.Espina como la de Irwin demoran minutos. He tomado parte de la solución de V.Espina para convertir el JSON a Colección, usando la propiedad useFastParser en .T., entonces obtengo una colección de fox rápidamente.

Me he puesto a implementar una conversión de colección a cursor, y me ha ido bastante bien. Cuando convierto el json principal a cursor1 todo bien. Cuando selecciono una celda de ese cursor (que es un json o colección), todo bien obtengo otro cursor2. Pero cuando selecciono una celda de este cursor2, que es un json con textos no he podido obtenerlo. Lo positivo es que mi rutina se demora segundos, y ya tengo los datos principales.

Alguien tendrá un camino más rápido para convertir un JSON a cusor, o colección a cursor.

Cualquier ayuda se las agradezco de antemano.
Buen día.

Miguel Antúnez

unread,
Feb 13, 2024, 2:32:36 PM2/13/24
to publice...@googlegroups.com
Hola Cristian, espero que esto te pueda ayudar.

--
Blog de la Comunidad Visual FoxPro en Español http://comunidadvfp.blogspot.com
---
Has recibido este mensaje porque estás suscrito al grupo "Comunidad de Visual Foxpro en Español" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a publicesvfoxp...@googlegroups.com.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/publicesvfoxpro/9f97bf03-6043-4b39-a7e5-7e20b74d2668n%40googlegroups.com.


--
Miguel Angel Antúnez Camones
mant...@gmail.com

Cristian Novoa

unread,
Feb 13, 2024, 3:35:49 PM2/13/24
to Comunidad de Visual Foxpro en Español
Gracias Miguel. Yo uso SQL Server 2012. Parece que es hora de cambiar de versión.

Cristian Novoa

unread,
Feb 13, 2024, 7:07:28 PM2/13/24
to Comunidad de Visual Foxpro en Español
Encontré oCursor = nfJsonRead(lcjson). Entrega una mezcla de matrices y objetos. Me retorna los datos que andaba buscando. Se demora un par de segundos. Tendré que replantear mi función para llegar al cursor. La clave de todo es usar AMEMBERS.

Zarlu

unread,
Feb 14, 2024, 12:40:24 PM2/14/24
to Comunidad de Visual Foxpro en Español
Buenas tardes novoacar!

No he trabajado con json, pero me gustaría intentar.
Tendrás alguno para hacer pruebas respecto de lo que quieres lograr?

Gracias
zarlu
Chetumal, Quintana Roo, México

IngeSis Ingeniería & Sistemas

unread,
Feb 14, 2024, 9:55:28 PM2/14/24
to Comunidad de Visual Foxpro en Español
Amigos, buenas noches. Tengo esta rutina para pasar Json a DBF y es súper rápido por si les sirve. Quedo atento a sus comentarios.
*-------------------------------------------------------------------------------------------------------------------------------*
* Json a DBF / Recibe un Json y Crea un CURSOR con sus Campos Json
* Todos tipo String Tamaño 80. (Pueden cambiarlo si se desea)
* Retorna .T. si Crea JsonDbf.DBF ó <nameFile.DBF>
* Autor: Andrés Palacio (IngeSis)
*-------------------------------------------------------------------------------------------------------------------------------*
PROCEDURE JsonToTabla(lcString as String) as Logical
USE IN SELECT("JsonDbf") && Cierro Tabla a Crear
ERASE JsonDbf.dbf
JTT = CHRTRAN(CHRTRAN(CHRTRAN(lcString,CHR(13),""), CHR(10),""), CHR(9),"") && Quito Enter + SaltosLínea + Tab
JTT = STRTRAN(JTT,[" : "],[":"]) && Quito Espacios para contar Objetos dentro de {}
JTT = IIF(LEFT(JTT,1)='[', JTT, "["+JTT+"]")
IF LEFT(JTT,1)="[" AND RIGHT(JTT,1)="]" && [ ]
nObj = OCCURS("}", JTT) && Nº Objetos adentro = "Registros" = Filas del Array
cCampos = ""
oReg = CHRTRAN(STREXTRACT(JTT,"{","}",1), ["], [])
nCam = OCCURS([:],oReg) && Nº Campos a crear = Columnas Array
DIMENSION ArrayCam[IIF(nObj>0,nObj,1), IIF(nCam>0,nCam,1)] && Array para Valores [Fil,Col]
FOR i = 1 TO nObj
oReg = CHRTRAN(STREXTRACT(JTT,"{","}",i), ["], [])
* Solo en Objeto 1 creo el Vector de "Campos".
IF i=1
FOR j=1 TO nCam && Veo los campos:valores
cam = GETWORDNUM(oReg, j, [,])
cCampos = cCampos + IIF(EMPTY(cCampos),"",[, ]) + GETWORDNUM(cam,1,":") + " C(80)"
ENDFOR
cCampos = CHRTRAN(cCampos,CHR(13),"")
ENDIF
* Lleno Array con los Valores
FOR j=1 TO nCam
ArrayCam(i,j) = STREXTRACT(oReg,[:], IIF(j=nCam,"",[,]), j)
ENDFOR
ENDFOR
* CREO LA TABLA solo si la Cadena cCampos viene con Valor. Y agrego valores del Array
cCampos = STRTRAN(cCampos, "saldoPrevio", "saldoPrev") && CORTO de 11 caracteres a 9. Solo es válido hasta 10.
IF !EMPTY(cCampos)
JsonT = IIF(VARTYPE(nameFile)='C', nameFile, "JsonDbf")
CREATE TABLE &JsonT (&cCampos)
APPEND FROM ARRAY ArrayCam
USE && Cierro la Tabla
ENDIF
nResul = IIF(EMPTY(cCampos),.F.,.T.) && Si creo cursor reporta .T. sino .F.
ENDIF
RETURN IIF(VARTYPE(nResul)='L', nResul, .F.)
ENDPROC
*===============================================================================================================================*

Cristian Novoa

unread,
Feb 14, 2024, 10:31:19 PM2/14/24
to Comunidad de Visual Foxpro en Español
Gracias ingesis. Me dio un error en la creación de un cursor. Al ejecutar el debug se ve que un campo del cusor no tiene nombre.

Pero lo anterior no es lo peor. Lo peor es que ya habían transcurrido 30 segundos, por lo que para mi problemática no me sirve.

Logré convertir mi json a cursor en 4 o 5 segundos, así que estoy bastante satisfecho, pero debo afinar algo utilizando nfJsonRead que retorna arrays y objetos.

¿ Cómo logré esto ?, son 3 pasos:

1) El obvio consumo de la API (retorna 68 artículos, el json es de 1.168.563 bytes). Esto demora 1 segundo.
2) Se convierte el json a colección, gracias a JSON.PRG de V.Espina, utilizando la propiedad useFastParser en verdadero. Esto demora unos 3 segundos aproximadamente.
3) La rutina que hice para convertir la colección a cursor (gracias a la función AMEMBERS). Esto demora 1 segundo aproximadamente.

Esto es nuevo para mi. Voy a publicar mi rutina cuando solucione el detalle que mencioné (un dato que no me devuelve la colección), y cuando la tenga más probada.

Hay que ver también que tan genérico queda esto, y si funciona en otros casos particulares.

Saludos.

Aarón Delgado

unread,
Feb 15, 2024, 8:33:37 AM2/15/24
to publice...@googlegroups.com
Excelente Cristian...!!!
No te conformaste con la demora del json.prg (gran aporte de Victor E.)

Saludos cordiales;

DELGADO JAIMES, Roberto Aarón
Fijo: 013969545 /  Movistar: 988316319



Cristian Novoa

unread,
Feb 15, 2024, 9:08:53 AM2/15/24
to Comunidad de Visual Foxpro en Español
Mil gracias a ti Roberto por asesorarme con la API. Un mundo desconocido para mi.

Un abrazo amigo.

Daniel Sánchez

unread,
Feb 16, 2024, 11:54:45 AM2/16/24
to publice...@googlegroups.com
Buenas, copia el siguiente código en un prg y pruebalo, quien sabe cumple con lo que necesitas nos comentas

FUNCTION cursortostr
PARAMETERS cAliasCursor, nAccion, cToStr, ltofile, cNameFile

*/cAliasCursor Nombre del cursor a obtener o pasar los datos
*/nAccion 1 pasar de tabla a cadena
*/ 2 de cadena a tabla cierra cursor si existe y lo crea con la estructura
*/ 3 si existe cursor no lo cierra y pasa los datos
*/cToStr   Cadena con los datos a pasar al cursor
*/ltofile Si es verdadero y la opcion 1 lo graba en un archivo los datos del cursor
*/ si la opcion es 2 o 3 lee los datos desde un archivo y lo carga al cursor
*/cNameFile Nombre del archivo a grabar o a leer segun nAccion

*/se va ha crear una estructura
*/ primer item la definicion de la tabla y las demas los datos de la tabla
*/ "{campo1,n,(10,2),|campo2,c,(30),|campo3, l,,|campo4,D,,|};{"campo1":8.30,"campo2" : "datos de texto","campo3" :.t.,"campo4" : 01/01/2021,};"

LOCAL lCrearTabla, cPalote, nICampos, cCampoAdd, cCampo, cTipo, cWidth, cDecimal,;
cToString, nIField, cFila, nItems, oFila, cAliasActual

IF VARTYPE(cNameFile)="L"
cNameFile="cursortostr.txt"
ENDIF

cAliasActual=ALIAS()
lCrearTabla=.f.

IF EMPTY(cAliasCursor)
RETURN -1
ENDIF

IF !USED(cAliasCursor) AND nAccion=1
RETURN -1
ELSE
IF nAccion=2 AND !USED(cAliasCursor)
lCrearTabla=.t.
ENDIF
ENDIF

IF nAccion=1 &&leer la tabla

*/obtenemos los campos de la tabla
cPalote="|"
nICampos=AFIELDS(aTabla,cAliasCursor)
cCampoAdd=""
FOR nIfield=1 TO nICampos
cCampo=ALLTRIM(aTabla[nIField,1])
cTipo=ALLTRIM(aTabla[nIField,2])
cWidth=ALLTRIM(STR(aTabla[nIField,3],3,0))
cDecimal=ALLTRIM(STR(aTabla[nIField,4],3,0))
cIsNull=TRANSFORM(aTabla[nIField,5])
cCampoAdd=cCampoAdd+cCampo+","+cTipo+","+cWidth+","+cDecimal+","+cIsNull+","+cPalote
ENDFOR
*SET STEP ON
cCampoAdd="{"+cCampoAdd+"};"
cFilasAdd=""
oField=.null.
*/ahora vamos a cargar los datos
SELECT (cAliasCursor)
SCAN
Scatter Memo Name oField
*/lo pasamos a json
ctxt=json.stringify(oField)
cCampoAdd=cCampoAdd+cTxt+";"
ENDSCAN
IF ltofile
nretorno=STRTOFILE(cCampoAdd,cNameFile)
ENDIF
RETURN cCampoAdd
ELSE
IF nAccion=2 OR nAccion=3 &&crear si no existe y llenar la tabla con los datos almancenados
*/recuperar la cabecera con los datos del cursor
IF ltofile
cToStr=FILETOSTR(cNameFile)
ENDIF
cCabecera=comboitems(cToStr,1)
nICampos=comboitems(cCabecera,-1,"|")
*/ahora lo pasamos a un array como el array original de la tabla
DIMENSION aTabla[nICampos,18]
FOR nIField=1 TO nICampos
cField=comboitems(cCabecera,nIField,"|")
cField=STRTRAN(cField,"{","")
aTabla[nIField,1]=comboitems(cField,1,",")
aTabla[nIField,2]=ALLTRIM(comboitems(cField,2,","))
aTabla[nIField,3]=INT(VAL(comboitems(cField,3,",")))
aTabla[nIField,4]=INT(VAL(comboitems(cField,4,",")))
aTabla[nIField,5]=(".T."=comboitems(cField,5,","))
aTabla[nIField,6]=.f.
aTabla[nIField,7]=""
aTabla[nIField,8]=""
aTabla[nIField,9]=""
aTabla[nIField,10]=""
aTabla[nIField,11]=""
aTabla[nIField,12]=""
aTabla[nIField,13]=""
aTabla[nIField,14]=""
aTabla[nIField,15]=""
aTabla[nIField,16]=""
aTabla[nIField,17]=0
aTabla[nIField,18]=0
ENDFOR  
*/preguntamos si exise el cursor
IF nAccion=2 AND USED(cAliasCursor) &&lo cerramos y lo volvemos a crear
SELECT (cAliasCursor)
USE
ENDIF
IF !USED(cAliasCursor)
CREATE CURSOR (cAliasCursor) from ARRAY aTabla
ENDIF
*/ahora si llenar sus datos
nItems=comboitems(cToStr,-1,"};")-1
IF nItems>0
FOR nIFilas=1 TO nItems
cFila=comboitems(cToStr,nIfilas+1,"};")
cFila=SUBSTR(cFila,2)+"}"
*/ahora lo pasamos a un objeto
oFila=json.parse(cFila)
INSERT INTO (cAliasCursor) FROM NAME oFila
ENDFOR  
ENDIF
ENDIF

ENDIF

IF !EMPTY(cAliasActual)
SELECT (cAliasActual)
ENDIF 

--
Blog de la Comunidad Visual FoxPro en Español http://comunidadvfp.blogspot.com
---
Has recibido este mensaje porque estás suscrito al grupo "Comunidad de Visual Foxpro en Español" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a publicesvfoxp...@googlegroups.com.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/publicesvfoxpro/9f97bf03-6043-4b39-a7e5-7e20b74d2668n%40googlegroups.com.


--
Daniel Sánchez Escobar
Investigación y Desarrollo
Reset Software SAC
Móvil y WhatsApp +051-949398047 / Móvil 948615385
Trujillo - Perú

P  Sugerimos no imprimir este e-mail a menos que sea absolutamente necesario. Protejamos el medio ambiente.

Cristian Novoa

unread,
Feb 16, 2024, 12:08:09 PM2/16/24
to Comunidad de Visual Foxpro en Español
Gracias Daniel. No encuentra "comboitems".

Daniel Sánchez

unread,
Feb 16, 2024, 12:24:46 PM2/16/24
to publice...@googlegroups.com
Llama también a esta funciòn comboitems, que te adjunto 

Parameter CITEMS As Character, NPOSICIONACTUAL As SHORT, cSeparador as Character
Local NVECES As Integer, NANTCOL, NACTCOL, NPOSICION, CVALOR
IF TYPE("cSeparador")="L"
cSeparador=";"
ENDIF
NVECES = Occurs(cSeparador, CITEMS)
If NPOSICIONACTUAL=-1
Return NVECES
ENDIF
IF nposicionactual=0
RETURN "No definido"
ENDIF
NPOSICIONACTUAL = Iif(NPOSICIONACTUAL=0, 1, NPOSICIONACTUAL)
If  .Not. Type("citems")="C"
Return ''
Endif
If Type("nposicionactual")="L" .Or. NPOSICIONACTUAL=0
Return ''
ENDIF
ncuantasveces=OCCURS(cSeparador,citems)
IF nposicionactual>nveces
nposicionactual=nveces
ENDIF
Store 0 To NANTCOL, NACTCOL
CVALOR = ''
If NVECES>=NPOSICIONACTUAL
NPOSANTERIOR = NPOSICIONACTUAL-1
NACTCOL = Atc(cSeparador, CITEMS, NPOSICIONACTUAL)
If NPOSANTERIOR>0
NANTCOL = Atc(cSeparador, CITEMS, NPOSANTERIOR)
Endif
NANTCOL = NANTCOL+1
NRETORNAR = (NACTCOL-NANTCOL)
CVALOR = Substr(CITEMS, NANTCOL, NRETORNAR)
Endif
Return CVALOR
Endfunc
**
Reply all
Reply to author
Forward
0 new messages