Hace unos meses comencé un proyecto llamado "El zorro peregrino" el cual consiste en mostrar el camino a través de la practica, a los foxeros que ya tienen sus años trabajando con este maravilloso lenguaje de programación; el camino mencionado es el de las nuevas tecnologías o tendencias de desarrollo.
He dicho por largo tiempo en grupos de debates y opiniones que la tecnología sube por ascensor y nosotros (los foxeros) subimos por escalera, esto quiere decir que cada dia literalmente nos hacemos más obsoletos y menos cotizables en el monstruoso mercado laboral.
Aún recuerdo aquella vez cuando fui a una entrevista de trabajo para desarrollador y me preguntaron que si hacía servicios web, entre mi dije, ¡Vaya, que será servicios web!, ¿será que son páginas web?, si digo que si entonces puede que me pregunten algo sobre eso y voy a quedar mal, más vale ser ignorante por 1 minuto que por toda la vida, mejor pregunto.
Les pregunté que si era hacer páginas web, me dijeron que sí entonces les dije que si sabia pero que no era mi fuerte. Más tarde me di cuenta de que me habian dicho que si solo porque ya no les interesaba y les daba igual mi respuesta.
Desde ese entonces sufri una gran decepción conmigo mismo porque no estaba al dia con los avances tecnológicos; me quedé estancado depurando errores en una empresa de software que terminaron cegándome al punto de sentir temor si algún dia me decidía a salirme del yugo patrono-empleado y comenzar mi carrera como freelancer.
Me di cuenta de que estaba muy por debajo del nivel que exigía el mundo tecnológico en ese momento asi que me dediqué a leer y actualizarme poco a poco, claro que siguiendo con Visual FoxPro porque era el que daba de comer (de hecho sigue dando).
Es por eso que comencé el proyecto El zorro peregrino, para que los programadores tengan una guia de como realizar la transición a este mundo moderno, seguramente muchos de los foxeros están desactualizados como me pasó a mi, lo puedo apostar porque en ese entonces era un venteañero, ahora tengo 33, soy un Foxero joven considerando los años que lleva el lenguaje y la cantidad de empresas de software que aún hoy dia siguen sostenidas por su software desarrollado en Visual FoxPro, lo cual se traduce en foxeros esparcidos por el mundo con un minimo de 15 años y un minimo de 45 años de edad.
Si fue dificil para mi adaptarme a las nuevas tendencias entonces no lo supone para ellos?
Bueno, dejemos tanta chachara y veamos el JSONFox
Es una libreria de código abierto que permite parsear JSON a un objeto o representación string, lo interesante de la librería es que nació de la necesidad de intercambiar información con las aplicaciones de Fox separadas en capas, por lo tanto era indispensable conseguir algún medio de transporte e intercambio de data entre los componentes de las capas y, sabiendo que Fox tiene compatibilidad bidireccional con Cursores y XML entonces se me ocurrió la idea de hacer el parser de JSON a XML y viceversa.
De esta manera ya tendríamos cubierta la necesidad de transportar data en formaro XML para luego serializar a un cursor (los cursores no se deben transferir entre capas)
Descarga la librería de github
https://github.com/Irwin1985/JSONFox
Hasta la próxima!!!
Hola Irwin, he descargado tu clase JsonFox, voy a empezar a probarlo en un pequeño proyecto en VFP9.
ResponderEliminarPor otro lado, qué pasó que ya no escribes más artículos? Son muy interesantes.
Saludos desde Lima, Perú.
Hola Skysurfer, la verdad pensaba que nadie leía mis artículos. Voy a considerar escribir más entonces... :)
EliminarBuenas tardes Irwin, poco conozco del desarrollo web, para que me sirve el formato Json desde Foxpro, me puede servir para subir datos desde una base de datos de SQL Server a MySQL a un hosting web? Gracias de antemano
ResponderEliminarSí, JSON es el formato estándar para el intercambio de datos entre aplicaciones o servicios web y otras aplicaciones de cualquier tipo (incluyendo desktop) por lo tanto para poder hablar con cualquier API por ahí de afuera es necesario conocer su lenguaje común que es HTTPRequest con respuestas JSON. Eso incluye desde luego comunicaciones con servidores de bases de datos siempre y cuando exista una API de por medio que te reciba las peticiones, te ejecute las consultas y te devuelva las respuestas.
EliminarBuen dia. Ante todo, agradezco tu importante aporte al abrir la librería para su consumo a toda la comunidad. Haciendo pruebas, noto que si deseo parsear un objeto que tiene una propiedad "Collection" con items incluidos, la coleccion no es parseada. Te paso un breve ejemplo:
ResponderEliminardo c:\jsonfox-master\jsonfox.app
ox = Createobject("Empty")
Addproperty(ox,"id",19191)
Addproperty(ox,"nombre","Fulano")
Addproperty(ox,"apellido","De Tal")
oY = Createobject("Collection")
oZ = Createobject("Empty")
Addproperty(oZ,"Nombre","Juana")
Addproperty(oZ,"Dni",36890765)
oY.Add(oz)
oZ = Createobject("Empty")
Addproperty(oZ,"Nombre","Laura")
Addproperty(oZ,"Dni",33786545)
oY.Add(oz)
Addproperty(ox,"hijas",oY)
cx = _screen.json.stringify(ox)
Hay algo que yo esté haciendo mal?
Nuevamente, muchas gracias
Ya he realizado la mejora y la puedes descargar desde aquí: https://github.com/Irwin1985/JSONFox
EliminarFue divertido realizar el cambio gracias a la estructura del código de la librería, hice todas las pruebas que se me ocurrieron pero ya sabes que siempre se escapa algo así que bienvenida sea cualquier otra detección de bugs.
Saludos!
Hola Alberto muchas gracias por usar la herramienta y en especial por darte cuenta de este bug de la librería. He tomado tu ejemplo como base para debuggear y me di cuenta que los objetos "Collection" pasan desapercibidos ante la función AMEMBERS() lo cual en efecto genera el vacío en todos los objetos que hereden de Collection. No me pasó por la mente testearlos pues siempre estuve cegado con la maravillosa clase "Empty".
ResponderEliminarMe has dado trabajo así que tendré la librería bajo mantenimiento hasta liberar la revisión. Debes marcar el repositorio como "Watching" para que te enteres cuando la libere y puedas probarla.
Saludos!
Saludos Irvin, felicitaciones por tus aportes, estoy probando _Screen.Json.JSONToCursor(lcJsonArray, "qTemp"), crea el cursor los campos pero sin datos y me muestra el mensaje "Data type mismatch", al probarlo desde un *.prg funciona normal, pero al ejecutarlo desde el formulario de mi aplicación me muestra ese mensaje "Data type mismatch", gracias por tu tiempo.
ResponderEliminarHola Fernando, ayúdame con tu contenido del array para poder hacer las pruebas con tu misma data y recrear el error. Gracias!
ResponderEliminarHola Irwin muchas gracias por el aporte, disculpa se tiene alguna dificultad con la librería si la fecha comienza con el día en lugar de con el año? ya que me sale un error relacionado a la fecha. Gracias.
ResponderEliminarHola, sí la tiene porque normalmente los webservices te devuelven la fecha en formato YYYY-mm-dd. Qué formato le estás pasando?
ResponderEliminarMuchas gracias por la respuesta, es un servicio web del diario oficial de la federación. y la fecha me la envía: dd-mm-YYYY. este es el servicio: https://sidofqa.segob.gob.mx/dof/sidof/indicadores/
ResponderEliminarSabes de alguna forma en la que pueda convertir la respuesta Json de ese servicio en XML para poder pintarla en el cursor. ? Gracias de ante mano
Ya está agregada la mejora, ahora JSONFox puede soportar fechas con formado dd-mm-YYYY y dd/mm/YYYY. https://github.com/Irwin1985/JSONFox
ResponderEliminarY para que lleves el Array a Cursor tienes este ejemplo:
Text To lcJsonStr NoShow
{
"messageCode": 200,
"response": "OK",
"ListaIndicadores": [
{
"codIndicador": 31001,
"codTipoIndicador": 158,
"fecha": "23-02-2021",
"valor": "20.6783"
},
{
"codIndicador": 30963,
"codTipoIndicador": 159,
"fecha": "23-02-2021",
"valor": "6.694871"
},
{
"codIndicador": 31002,
"codTipoIndicador": 165,
"fecha": "23-02-2021",
"valor": "4.2875%"
},
{
"codIndicador": 31003,
"codTipoIndicador": 166,
"fecha": "23-02-2021",
"valor": "4.2620%"
},
{
"codIndicador": 31004,
"codTipoIndicador": 175,
"fecha": "23-02-2021",
"valor": "4.04%"
}
]
}
endtext
obj = _screen.json.parse(lcJsonStr)
ACOPY(obj.listaindicadores, otroArray)
lcArray = _screen.json.stringify(@otroArray)
?lcArray
_screen.json.jsontocursor(lcArray, "qData")
select qData
browse
Muchas gracias por el apoyo, estoy comenzando en el mundo del VFP por un proyecto de mi trabajo y solo se usar tu librería la que termina en prg y no la que termina en app, con esta actualización que hiciste también se vería reflejado en la prg?
ResponderEliminarloRest = NEWOBJECT("rest", "C:\Users\capacitaciones\Documents\VFPRestClient-master\vfprestclient.prg")
ResponderEliminarloRest.AddRequest(loRest.GET, "https://sidofqa.segob.gob.mx/dof/sidof/indicadores/")
loRest.Send()
?loRest.status
?loRest.lASTERRORTEXT
?loRest.resPONSE
loJson = NEWOBJECT ("jsonfox","C:\Users\capacitaciones\Documents\JSONFox\jsonfox.prg")
obj = loJson.decode(loRest.resPONSE)
?obj
cXML = loJson.arraytoxml(obj._listaindicadores)
?cxml
XMLTOCURSOR(cxml,"prueba")
browse
este es el codigo que estoy utilizando
Usalo así:
ResponderEliminarloRest = NEWOBJECT("rest", "C:\Users\capacitaciones\Documents\VFPRestClient-master\vfprestclient.prg")
loRest.AddRequest(loRest.GET, "https://sidofqa.segob.gob.mx/dof/sidof/indicadores/")
loRest.Send()
Do locfile("jsonfox", "app")
obj = _screen.json.parse(loRest.resPONSE)
ACOPY(obj.listaindicadores, otroArray)
lcArray = _screen.json.stringify(@otroArray)
_screen.json.jsontocursor(lcArray, "qData")
select qData
browse
Muchas gracias amigo por el apoyo, ya quedó. al momento de ejecutarlo me sale el visual FoxPro Debugger [break]-jasonclass.prg:jsonclass.parse. precioso play y ya se genera el cursor, hay alguna forma de que se pueda ejecutar el cursor si tener que presionar el play del debugger? Gracias y si me pudieras propocionar alguna numero de cuenta de bbva para hacerte una transfer. Saludos.
ResponderEliminarRevisa si la JsonClass.prg tiene una instrucción SET STEP ON y quítala.
ResponderEliminarIrwin,me quito el sombrero por la facilidad con que has realizado y mostrado la integración del fox con las nuevas tecnologías.
ResponderEliminarMuchas gracias por tus aportes
Hola Jorge gracias a ti por estar atento a mis publicaciones. Un saludo!
ResponderEliminarBuenas tardes Irwin, estoy probando tu librería, no se si estoy haciendo algo mal, pero solo convierte a cursor (JsonToCursor) el primer registro, aunque hay 2 en el Json, espero puedan ayudarme a ver que me falta, gracias. Aquí el código:
ResponderEliminar** PRUEBA JSONFOX
SET DECIMALS TO 4
Do LocFile("JSONFox", "app")
SET MEMOWIDTH TO 8000
LC_JSTEXT = ""
TEXT TO LC_JSTEXT NOSHOW ADDITIVE
{"status": "success",
"vart_ajus":[
{"art_check":1,"pk_lam":"00001","fact_num":0,"reng_num":1,"art_num":1,"co_art":"LGIS001","co_alma":"000012","art_alto":1.2568,"art_ancho":2.4550,"art_dim":3.0854,"art_alto_stock":0,"art_ancho_stock":0,"art_dim_stock":0,"art_unid":"","art_ubic":"","art_pint":"","art_iso":"000000000000","art_com":"","art_fec":"2021-06-27 12:00 AM"},
{"art_check":1,"pk_lam":"00002","fact_num":0,"reng_num":1,"art_num":2,"co_art":"LGIS001","co_alma":"000012","art_alto":2,"art_ancho":1,"art_dim":2,"art_alto_stock":0,"art_ancho_stock":0,"art_dim_stock":0,"art_unid":"","art_ubic":"","art_pint":"","art_iso":"000000000000","art_com":"","art_fec":"2021-06-27 12:00 AM"}
],
"code": 200,
"message": "success"}
ENDTEXT
*LC_JSTEXT = Strtran(LC_JSTEXT, Chr(13)+Chr(10), "") && Eliminar los saltos de línea
obj = _Screen.Json.Parse(LC_JSTEXT)
If _Screen.Json.lError
MessageBox(_Screen.Json.LastErrorText, 48, "Something went wrong")
Return
ENDIF
* Encode just the Array attribute called (data)*
lcJsonArray = _Screen.Json.Encode(obj.vart_ajus)
* Surround the lcJSONArray with array character delimiters '[' ']'.
lcJsonArray = "[" + lcJsonArray + "]"
*messagebox(lcJsonArray)
* Convert the JSONArray into VFP CURSOR **(this is cool)**
_Screen.Json.JsonToCursor(lcJsonArray, "cursorxx")
BROWSE NORMAL
Hola José,
ResponderEliminarTe devuelvo el mismo ejemplo con los cambios enumerados para que sepas lo que hubo que hacer para tratar los arrays.
** PRUEBA JSONFOX
SET DECIMALS TO 4
Do LocFile("JSONFox", "app")
SET MEMOWIDTH TO 8000
LC_JSTEXT = ""
TEXT TO LC_JSTEXT NOSHOW ADDITIVE
{"status": "success",
"vart_ajus":[
{"art_check":1,"pk_lam":"00001","fact_num":0,"reng_num":1,"art_num":1,"co_art":"LGIS001","co_alma":"000012","art_alto":1.2568,"art_ancho":2.4550,"art_dim":3.0854,"art_alto_stock":0,"art_ancho_stock":0,"art_dim_stock":0,"art_unid":"","art_ubic":"","art_pint":"","art_iso":"000000000000","art_com":"","art_fec":"2021-06-27 12:00 AM"},
{"art_check":1,"pk_lam":"00002","fact_num":0,"reng_num":1,"art_num":2,"co_art":"LGIS001","co_alma":"000012","art_alto":2,"art_ancho":1,"art_dim":2,"art_alto_stock":0,"art_ancho_stock":0,"art_dim_stock":0,"art_unid":"","art_ubic":"","art_pint":"","art_iso":"000000000000","art_com":"","art_fec":"2021-06-27 12:00 AM"}
],
"code": 200,
"message": "success"}
ENDTEXT
*LC_JSTEXT = Strtran(LC_JSTEXT, Chr(13)+Chr(10), "") && Eliminar los saltos de línea
obj = _Screen.Json.Parse(LC_JSTEXT)
If _Screen.Json.lError
MessageBox(_Screen.Json.LastErrorText, 48, "Something went wrong")
Return
ENDIF
* Encode just the Array attribute called (data)*
*===========================================================*
* 1. Copiar el array desde obj.vart_ajus a array1
*===========================================================*
acopy(obj.vart_ajus, array1)
*===========================================================*
* 2. pasar la copia array1 como referencia usando '@'
*===========================================================*
lcJsonArray = _Screen.Json.Encode(@array1)
* Surround the lcJSONArray with array character delimiters '[' ']'.
*===========================================================================*
* 3. No hace falta delimitar con corchetes porque ya se trata de un array.
*===========================================================================*
*lcJsonArray = "[" + lcJsonArray + "]"
*messagebox(lcJsonArray)
* Convert the JSONArray into VFP CURSOR **(this is cool)**
_Screen.Json.JsonToCursor(lcJsonArray, "cursorxx")
BROWSE NORMAL
Este comentario ha sido eliminado por el autor.
ResponderEliminarEstimados
ResponderEliminarEstoy recien incursionando en las api de las cuales me devuelve un JSON
Necesito de su ayuda como puedo pasar a una tabla o cursor los datos que me entrega una api las cuales son tandas de 50 filas de la siguiente forma
Para obtener los datos uso lo siguiente
Public lcjonStr as string
xmlHttp = CREATEOBJECT("Microsoft.XMLHTTP")
xmlHttp.open("get", 'https://api.xxx/api/v2/unidad/585/detalles', .f.)
xmlHttp.setRequestHeader("Authorization","Token yyyy")
xmlHttp.setRequestHeader("Content-Type", "application/json")
xmlHttp.send()
IF xmlHttp.status = 200
lcJsonStr=STRCONV(xmlHttp.responseText,1)
y me devuelve
{
"links": { "current": "https://api.xxx/resumen?cursor=NUl899o80="
},
"data": [
{
"id": 882
"id_chek": 576,
"total": 113740,
"organizacion": {
"4.3": [
"Octogonal"
]
},
"diagnosticos": [],
"links": [
{
"rel": "self",
"href": "https://api.xxx/resumen/882",
"method": "GET"
}
]
},
{
"id": 882,
"id_check": 576,
"total": 2310,
"organizacion": {
"2.6": [
"Cuadrada"
]
},
"diagnosticos": [],
"links": [
{
"rel": "self",
"href": "https://api.xxx/resumen/882",
"method": "GET"
}
]
}
]
}
En este ejercicio recibo dos filas. NO se como recorrerlo o pasar a cursor ya que me dice data no encontrada. Muchas Gracias de antemano
Esto es lo que sucede, tu array no es compatible con el esquema de una tabla o cursor (columna, fila) y por eso no es posible hacer la conversión a cursor directamente.
EliminarTu array contiene un objeto llamado "organización" y ese es el que está impidiendo la conversión. La solución en estos casos es recorrer el array de forma manual e ir sacando los datos en un cursor maestro y otro detalle porque imagino que quieres conservar la relación de la data con los diagnósticos.
Puedo ayudarte de forma gratuita pero no te prometo fecha de entrega porque ahora estoy siendo más padre que programador :). Por otra parte, ofrezco consultorías los Martes y Jueves de 8pm a 10pm (hora España) por si lo necesitas urgente. Aquí te dejo mi correo por si me quieres escribir directamente: rodriguez.irwin@gmail.com
MUchas gracias, como se recorro manualmente el array como saber la cantidad de filas antes usaba el json.prg pero ahora no me reconoce
ResponderEliminarn = ALEN(objeto._data.array)
para recorrerlo como
for i = 1 to n
? objeto._data.array[i]._diagnostico
next
Gracias por tu pronta respuesta
Estimado era simple
ResponderEliminarn = ALEN(obj.data)
gracias totales
ResponderEliminarHola
ResponderEliminaresto me funciona, pero como sería con tu función, ya que no encuentro la forma de pasarle la clave
loXml = CREATEOBJECT("MSXML2.XMLHTTP")
loxml.Open("GET", "url", .t.)
loxml.setRequestHeader("Content-Type", "application/json")
loxml.setRequestHeader("Authorization", "Basic clave")