json — n_pbt_json #
← Referencia de componentes · Índice de la guía
Construir un JSON tipo por tipo — texto, número, booleano, arreglo, objeto anidado — con el escapado hecho por usted, y luego leer uno a lo largo de una ruta:
of_load,of_get_string,of_type,of_count. Un solo objeto construye sus peticiones y lee sus respuestas. Todo en PowerScript puro: sin página, sin motor, PowerBuilder 10 incluido.
▶ Verlo en vivo — Aplicación de demostración, mosaico JSON: los resultados, el código que los produce y esta página, lado a lado.
En resumen #
n_pbt_json es autoinstantiate: se declara como variable local, sin create ni destroy. Es el mismo objeto que, internamente, construye las cargas útiles enviadas al motor — ahora ofrecido a su código, del lado de construcción y de lectura.
Inicio rápido #
Construir una carga útil y luego releer una respuesta — todo cabe en una variable local:
// Local variables
n_pbt_json lnv_json
string ls_customer
double ld_total
// Write : each member is typed and escaped for you - a path may have levels
lnv_json.of_set_string(/*path*/ "customer", /*value*/ "Ada")
lnv_json.of_set_number(/*path*/ "total", /*value*/ 690.50)
lnv_json.of_set_boolean(/*path*/ "paid", /*value*/ true)
// lnv_json.of_text() -> {"customer":"Ada","total":690.5,"paid":true}
// Read : load a response, reach values by path
lnv_json.of_load(/*json*/ '{"order":{"customer":"Ada","total":690.50}}')
IF lnv_json.of_is_valid() THEN
ls_customer = lnv_json.of_get_string(/*path*/ "order/customer") // Ada
ld_total = lnv_json.of_get_number(/*path*/ "order/total") // 690.5
END IF
Una ruta son las claves desde la raíz unidas por /; el índice de un arreglo es su posición, contada desde 1, como toda posición de la biblioteca: order/lines/1 es la primera línea, order/lines/0 no designa nada — una escritura lo rechaza con -5. Un nivel se escribe como lo escribe JSON Pointer (RFC 6901): ~1 es un / de la clave y ~0 un ~ (paths/~1users lee la clave /users; of_escape_key convierte una clave), un nivel vacío es la clave "" (a//b), y una ruta puede empezar por / — la forma completa del puntero, la única manera de nombrar la clave "" de la raíz (/). Si un objeto escribe la misma clave dos veces, es su PRIMERA aparición la que se lee y se escribe — un navegador conserva la última.
Construir una carga útil #
| Método | Función |
|---|---|
of_add_string (string as_path, string as_value) → long | Añade una CADENA, con escape automático, al ARRAY en as_path. El array debe existir: ábralo antes con of_set_raw y un array vacío. Devuelve 0, -4 si as_path falta o no es un array, -5 si un nivel de as_path es un índice 0 en un array; una cadena nula se escribe vacía (para un null JSON: of_add_raw(as_path, "null")) |
of_add_boolean (string as_path, boolean ab_value) → long | Añade un BOOLEANO (true o false, nunca entre comillas) al ARRAY en as_path. El array debe existir: ábralo antes con of_set_raw y un array vacío. Devuelve 0, -4 si as_path falta o no es un array, -5 si un nivel de as_path es un índice 0 en un array; un valor nulo escribe null |
of_add_number (string as_path, long al_value) → long | Añade un NÚMERO (cinco sobrecargas: integer, long, longlong, decimal, double — un decimal y un longlong conservan TODAS sus cifras (los céntimos de un importe, la última cifra de un identificador por encima de 2^53), y un literal como 690.50 es un decimal, escrito 690.5) al ARRAY en as_path. El array debe existir: ábralo antes con of_set_raw y un array vacío. Devuelve 0, -4 si as_path falta o no es un array, -5 si un nivel de as_path es un índice 0 en un array; un valor nulo escribe null |
of_add_raw (string as_path, string as_json) → long | Añade un valor YA en JSON (un objeto, un array) del que usted responde al ARRAY en as_path. El array debe existir: ábralo antes con of_set_raw y un array vacío. Devuelve 0, -4 si as_path falta o no es un array, -5 si un nivel de as_path es un índice 0 en un array; un valor nulo o vacío escribe null. La ruta vacía es la RAÍZ: of_load("[]") y luego of_add_raw("", …) construye un documento que es un array (el cuerpo de una llamada de API por lotes). Añadir muchos elementos seguidos al mismo array sigue siendo rápido |
of_set_array (string as_path, string as_values[]) → long | ESCRIBE un ARRAY entero de cadenas en as_path desde un array PowerBuilder, cada elemento con escape. Un array vacío escribe uno vacío, un elemento nulo una cadena vacía. Misma regla de ruta y mismos códigos que of_set_string |
of_set_members (string as_fragment) → long | Fusiona en la RAÍZ miembros ya formados en otro sitio, unidos por comas. Una clave que la raíz ya tiene ve su valor reemplazado en el sitio, una nueva se añade al final, una clave que el fragmento repite conserva su último valor. Un fragmento vacío no escribe nada. Devuelve 0, -4 si la raíz del documento no es un objeto |
of_clear ( ) → long | Vacía el documento para empezar otro objeto con la misma variable. Devuelve 0 |
of_text ( ) → string | El documento tal cual (compacto): lo que construyó (of_add_string, of_add_number...) o cargó (of_load), tras cualquier cambio — la salida única, lista para enviar, almacenar o reescribir. of_pretty da la forma indentada. {} si está vacío; llamarlo no vacía nada |
Leer un documento #
| Método | Función |
|---|---|
of_load (string as_json) → long | Carga un texto JSON para su lectura. Devuelve 0 si está bien formado, -5 si el argumento está vacío o en blanco (espacios, tabulaciones, saltos de línea), -4 si no es JSON válido o anida más de 512 niveles (el documento se descarta entonces). Analiza en PowerScript puro. Un BOM (U+FEFF) al principio, el de un archivo guardado en UTF-8 con BOM, se ignora. Con un código negativo, of_get_last_error dice dónde está mal el texto (línea, columna) y of_error_position en qué carácter. Un documento puede ser un solo valor ("abc", 42, null): se lee en la ruta vacía, no se escribe nada en él |
of_is_valid ( ) → boolean | Verdadero cuando el objeto contiene un documento: el último of_load tuvo éxito, o se ha escrito algo desde entonces. Un valor pasado a of_set_raw / of_add_raw no se vuelve a comprobar |
of_exists (string as_path) → boolean | Verdadero cuando existe un valor en la ruta dada — distingue un valor presente pero vacío de uno ausente |
of_type (string as_path) → string | El tipo JSON en la ruta: object, array, string, number, boolean, null; vacío si ausente |
of_get_string (string as_path) → string | El valor en la ruta, como texto: una cadena vuelve decodificada, un número/booleano/null como texto, un objeto o arreglo como JSON en bruto (recargable con of_load); una clave escrita dos veces se lee en su PRIMERA aparición |
of_get_number (string as_path) → double | El número en la ruta, como double — el punto decimal se respeta en cualquier máquina (2.5 es 2,5, no 2). 0 si ausente; el exponente se resuelve (1e-7, 2.5E+3) y se conservan 17 cifras significativas, ceros iniciales del exponente incluidos. Para un importe o un identificador que debe conservar todas sus cifras: of_get_decimal o of_get_longlong. Una cadena solo cuenta si es entera un número JSON: "12.50" vale 12,5, "12 kg" y "1,5" valen 0 |
of_get_decimal (string as_path) → decimal | El número en la ruta, como decimal, reconstruido a partir del TEXTO del número y nunca mediante un double: 12345678901234.56 vuelve con sus céntimos, 2.5E-3 vale 0.0025. 28 cifras significativas como máximo. 0 si ausente, si el valor no es un número, o más allá de lo que cabe en un decimal; una cadena solo cuenta si es entera un número ("12.50") |
of_get_longlong (string as_path) → longlong | El número en la ruta, como entero de 64 bits, reconstruido a partir de su texto y nunca mediante un double: un identificador de base de datos como 9007199254740993 vuelve entero. Los decimales se truncan (2.9 da 2). 0 si ausente, si el valor no es un número, o fuera del rango de un longlong; una cadena solo cuenta si es entera un número ("12.50") |
of_get_boolean (string as_path) → boolean | El booleano en la ruta: verdadero para el literal JSON true y para la cadena "true" que escriben algunas API; falso para todo lo demás |
of_count (string as_path) → long | El número de miembros del objeto, o de elementos del arreglo, en la ruta. Devuelve -1 si el valor es escalar o ausente (distingue un arreglo vacío, 0, de uno faltante, -1). Con of_name se recorre un objeto; un arreglo se recorre por su índice en la ruta (rows/1, rows/2…). Llamado en cada vuelta de un bucle, ya no cuesta nada una vez contado el arreglo, eliminaciones incluidas |
of_name (string as_path, long al_index) → string | El nombre del miembro n.º al_index (desde 1) del objeto en la ruta — para leer las claves de un objeto de forma desconocida. Con of_count, recorre el objeto. Para hacer de él un nivel de ruta: of_escape_key (una clave puede contener un /) |
of_escape_key (string as_key) → string | Una CLAVE escrita como UN nivel de ruta (JSON Pointer, RFC 6901): un ~ se vuelve ~0, luego un / se vuelve ~1 — la clave application/json es el nivel application~1json. Lo que necesita una clave leída por of_name antes de entrar en una ruta |
of_get_array (string as_path, ref string as_values[]) → long | Todos los elementos del arreglo en la ruta, en orden, en as_values (vaciado antes) — cada uno como lo lee of_get_string: una cadena vuelve decodificada, un número o un booleano como texto, null como "", un objeto o un arreglo como JSON en bruto (para cargar con of_load en otro n_pbt_json). "" es la raíz. Devuelve el número de elementos (0 para un arreglo vacío), -4 cuando no hay un arreglo en la ruta (nada, un objeto, un escalar), -5 cuando un nivel de la ruta es un índice 0 sobre un arreglo |
of_pretty ( ) → string | El documento — cargado o construido — re-indentado para la lectura (varias líneas, tabulaciones) — un log, un cuadro de texto. Vacío si no hay ninguno, o si un valor puesto con of_set_raw anida más de 512 niveles (el texto no sería el documento) |
of_pretty (long al_indent) → string | El documento — cargado o construido — re-indentado con al_indent espacios por nivel (2 y 4 son los anchos habituales). 0 lo escribe compacto, en una línea y sin espacios: el texto más pequeño para almacenar o enviar. Vacío si no hay documento, o si al_indent es negativo, mayor que 16 o null, o si un valor puesto con of_set_raw anida más de 512 niveles. of_pretty() sin argumento conserva las tabulaciones |
// Local variables
n_pbt_json lnv_json
string ls_tags[]
string ls_compact
long ll_count
// Read every element of an array at once, then store the document on one line
lnv_json.of_load(/*json*/ '{"customer":{"name":"Ada","tags":["vip","b2b"]}}')
ll_count = lnv_json.of_get_array(/*path*/ "customer/tags", /*values*/ ls_tags) // 2 : vip, b2b
// The document on one line, without a space : the smallest text to store
ls_compact = lnv_json.of_pretty(/*indent*/ 0)
Modificar un documento #
El lado de escritura cambia el documento cargado en el sitio, luego of_text devuelve el resultado (compacto) — lo que se reescribe. Los setters reemplazan el valor en la ruta, o agregan la última clave cuando falta en un objeto padre. Cada uno devuelve 0, -4 cuando un nivel del camino es un escalar, o un array sin ese índice, -5 con una ruta vacía o un índice 0 sobre un array. Un array encontrado en el camino se atraviesa con un índice que EXISTE (items/1/qty añade qty al primer elemento); solo se crea una clave de objeto. Un valor null (número, booleano, JSON en bruto vacío) se escribe null. Un bucle de escrituras, de claves añadidas o de eliminaciones en un documento grande (2 000 filas) sigue siendo rápido: cada llamada solo relee lo que toca.
| Miembro | Función |
|---|---|
of_set_string (string as_path, string as_value) → long | ESCRIBE una cadena en as_path, con escape automático. La ruta puede tener VARIOS niveles (a/b/c): los que faltan se crean como OBJETOS, y un documento VACÍO pasa a serlo — escribir ES construir. Un valor ya presente se reemplaza, esté donde esté. Una clave que contiene un / se escribe ~1 en la ruta (of_escape_key). Un bucle de escrituras en un documento grande sigue siendo rápido. Devuelve 0, -4 si un nivel del camino es un escalar, o un array sin ese índice (un array se atraviesa con un índice existente: items/1/qty), -5 con una ruta vacía o un índice 0 sobre un array. Una cadena nula se escribe vacía; para un null JSON: of_set_raw(as_path, "null") |
of_set_number (string as_path, long al_value) → long | ESCRIBE un NÚMERO en as_path, el punto decimal forzado. Cinco sobrecargas: integer, long, longlong, decimal, double — un decimal y un longlong conservan TODAS sus cifras (los céntimos de un importe, la última cifra de un identificador por encima de 2^53), y un literal como 690.50 es un decimal, escrito 690.5. Misma regla de ruta y mismos códigos que of_set_string; un valor nulo escribe null |
of_set_boolean (string as_path, boolean ab_value) → long | ESCRIBE un BOOLEANO en as_path: true o false, nunca entre comillas. Misma regla de ruta y mismos códigos que of_set_string; un valor nulo escribe null |
of_set_raw (string as_path, string as_json) → long | ESCRIBE en as_path un valor YA en JSON — un objeto anidado, un array, null — tal cual: usted responde por él. Así se ABRE también un array antes de of_add_*. Misma regla de ruta y mismos códigos que of_set_string; un valor nulo o vacío escribe null |
of_remove (string as_path) → long | Quita el valor en la ruta — un miembro de objeto (su clave y una coma se van con él) o un elemento de arreglo; el resultado sigue siendo válido. Devuelve 0, -4 si no hay nada, -5 con una ruta vacía o un índice 0 sobre un array |
// Local variables
n_pbt_json lnv_json
// Load, edit in place, then read back the ONE document with of_text
lnv_json.of_load(/*json*/ '{"name":"Ada","active":false}')
lnv_json.of_set_string(/*path*/ "name", /*value*/ "Grace") // replace
lnv_json.of_set_boolean(/*path*/ "active", /*value*/ true)
lnv_json.of_set_number(/*path*/ "count", /*value*/ 3) // added : the key was absent
// lnv_json.of_text() -> {"name":"Grace","active":true,"count":3}
Fechas #
Una fecha se escribe y se lee en ISO 8601 — lo que escriben las API, los navegadores y Python —, sea cual sea el formato de fecha del equipo: una fecha "2026-10-10", una fecha-hora "2026-10-10T14:30:00" (su fracción de segundo sigue cuando no es nula), una hora "14:30:00". Un valor nulo escribe null.
| Método | Función |
|---|---|
of_set_date (string as_path, date ad_value) → long | ESCRIBE una fecha en as_path (yyyy-mm-dd). La misma regla de ruta que of_set_string: devuelve 0, -4 si un nivel del camino es un escalar o un array sin ese índice, -5 con una ruta vacía o un índice 0 sobre un array |
of_set_datetime (string as_path, datetime adt_value) → long | ESCRIBE una fecha-hora (yyyy-mm-ddThh:mm:ss, la fracción de segundo tras un punto cuando no es nula). No se escribe ninguna zona horaria: la hora es la dada. Devuelve 0, -4 o -5, como of_set_date |
of_set_time (string as_path, time at_value) → long | ESCRIBE una hora (hh:mm:ss). Devuelve 0, -4 o -5, como of_set_date |
of_add_date (string as_path, date ad_value) → long | Añade una fecha al ARRAY en as_path. Devuelve 0, -4 si as_path falta o no es un array, -5 si un nivel de as_path es un índice 0 en un array |
of_add_datetime (string as_path, datetime adt_value) → long | Añade una fecha-hora al ARRAY en as_path. Devuelve 0, -4 o -5, como of_add_date |
of_add_time (string as_path, time at_value) → long | Añade una hora al ARRAY en as_path. Devuelve 0, -4 o -5, como of_add_date |
of_get_date (string as_path) → date | La fecha escrita en la ruta ("2026-10-10", o la fecha de una fecha-hora). 1900-01-01 si el valor falta, no es una fecha o nombra un día que no existe (2026-02-30); of_exists y of_type distinguen un valor ausente |
of_get_datetime (string as_path) → datetime | La fecha-hora escrita en la ruta: una T o un espacio entre fecha y hora, con o sin segundos, con fracción de segundo, o una fecha sola (medianoche). Una Z o un desfase (+02:00) se lee y no se aplica: la hora es la escrita — conviértala usted cuando la zona importa. 1900-01-01 00:00:00 si falta o no es una fecha |
of_get_time (string as_path) → time | La hora escrita en la ruta ("14:30", "14:30:00", "14:30:00.250", o la hora de una fecha-hora). 00:00:00 si falta, no es una hora, o una fecha sola |
// Local variables
n_pbt_json lnv_json
date ld_due
datetime ldt_created
// Write : ISO 8601, whatever the date format of the machine
lnv_json.of_set_date(/*path*/ "due", /*value*/ Date(2026, 10, 31))
lnv_json.of_set_datetime(/*path*/ "created", /*value*/ DateTime(Date(2026, 10, 10), Time(14, 30, 0)))
// Read what an API writes : the Z is read, the hour stays the one written
lnv_json.of_load(/*json*/ '{"due":"2026-10-31","created":"2026-10-10T14:30:00Z"}')
ld_due = lnv_json.of_get_date(/*path*/ "due")
ldt_created = lnv_json.of_get_datetime(/*path*/ "created")
Un DataStore en JSON, y vuelta #
PowerBuilder solo tiene ExportJson e ImportJson a partir de la 2017 R2. n_pbt_json lo hace desde PowerBuilder 10, tipado por las columnas: una cadena, un número (un decimal conserva todas sus cifras), una fecha yyyy-mm-dd, una fecha-hora, una hora, null para un NULL. Una sobrecarga toma un datawindow, otra un datawindowchild.
| Método | Función |
|---|---|
of_from_datastore (string as_path, datastore ads_source) → long | ESCRIBE las filas del búfer principal como un ARRAY de objetos en as_path: un objeto por fila, un miembro por columna, con el nombre de la columna. La ruta vacía hace del DOCUMENTO ese array (el cuerpo de una llamada por lotes). Devuelve el número de filas escritas, -5 si el DataStore no es válido o no tiene columnas, si no lo que devuelve of_set_raw |
of_to_datastore (string as_path, datastore ads_target) → long | INSERTA el ARRAY de objetos en as_path en un DataStore: una fila por objeto, cada miembro en la columna del mismo nombre (sin distinguir mayúsculas), convertido al tipo de la columna — un número desde un número o desde una cadena que es entera un número, una fecha, una fecha-hora o una hora desde un texto ISO, NULL para un null o un valor que la columna no puede contener. Un miembro que no nombra ninguna columna se ignora, un elemento que no es un objeto no crea fila. Las filas son NUEVAS: Update las inserta. Devuelve el número de filas insertadas, -5 si el DataStore no es válido o no tiene columnas, -4 si no hay array en as_path |
// Local variables
n_pbt_json lnv_json
datastore lds_orders
long ll_rows
string ls_body
// Send : every row of a retrieved DataStore as typed objects - the body of the call
lds_orders = create datastore
lds_orders.DataObject = "d_orders"
lds_orders.SetTransObject(SQLCA)
lds_orders.Retrieve()
ll_rows = lnv_json.of_from_datastore(/*path*/ "orders", /*source*/ lds_orders)
ls_body = lnv_json.of_text()
// Receive : the objects of a response inserted as NEW rows, ready for Update
lds_orders.Reset()
lnv_json.of_load(/*json*/ '{"data":[{"id":7,"customer":"Grace","amount":"19.99","due":"2026-12-24"}]}')
ll_rows = lnv_json.of_to_datastore(/*path*/ "data", /*target*/ lds_orders)
destroy lds_orders
Cuando el texto no es JSON #
| Método | Función |
|---|---|
of_get_last_error ( ) → string | Por qué la última llamada devolvió un código negativo; tras un of_load rechazado, dónde está mal el texto y por qué: line 2, column 6 : ':' expected after a key. Vacío tras una llamada correcta |
of_error_position ( ) → long | Devuelve la posición, contada desde 1 en el texto dado al último of_load (un BOM incluido), del carácter donde ese texto se vuelve erróneo — para seleccionar en un editor; 0 cuando el último of_load tuvo éxito |
// Local variables
n_pbt_json lnv_json
long ll_rc
string ls_why
long ll_where
// A response with a colon missing on its second line
ll_rc = lnv_json.of_load(/*json*/ '{"id":4152,~r~n "paid" true}')
IF ll_rc < 0 THEN
ls_why = lnv_json.of_get_last_error() // line 2, column 9 : ':' expected after a key
ll_where = lnv_json.of_error_position() // 22
END IF
Alcance. El JSON se analiza en PowerScript puro, sin página ni motor:
n_pbt_jsonsigue siendo autoinstantiate y funciona en todas partes, PowerBuilder 10 incluido. Para XML, vea xml (que se apoya en el motor); para mostrar un JSON como árbol plegable, vea jsontree.