json — n_pbt_json #
← Riferimento dei componenti · Sommario della guida
Costruire un JSON tipo per tipo — stringa, numero, booleano, array, oggetto annidato — con l'escaping fatto per te, poi rileggerne uno lungo un percorso:
of_load,of_get_string,of_type,of_count. Un solo oggetto costruisce le tue richieste e legge le tue risposte. Tutto in PowerScript puro: nessuna pagina, nessun motore, PowerBuilder 10 incluso.
▶ Vederlo dal vivo — Applicazione dimostrativa, riquadro JSON: i risultati, il codice che li produce e questa pagina, fianco a fianco.
In breve #
n_pbt_json è autoinstantiate: lo si dichiara come variabile locale, senza create né destroy. È lo stesso oggetto che, internamente, costruisce i payload inviati al motore — ora offerto al tuo codice, sul lato costruzione e lettura.
Avvio rapido #
Costruire un payload, poi rileggere una risposta — tutto in una variabile locale:
// 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
Un percorso sono le chiavi dalla radice unite da /; l'indice di un array è la sua posizione, contata da 1, come ogni posizione della libreria: order/lines/1 è la prima riga, order/lines/0 non designa nulla — una scrittura lo rifiuta con -5. Un livello si scrive come lo scrive JSON Pointer (RFC 6901): ~1 è un / della chiave e ~0 un ~ (paths/~1users legge la chiave /users; of_escape_key converte una chiave), un livello vuoto è la chiave "" (a//b), e un percorso può iniziare con / — la forma completa del puntatore, l'unico modo di nominare la chiave "" della radice (/). Se un oggetto scrive la stessa chiave due volte, è la sua PRIMA occorrenza a essere letta e scritta — un browser conserva l'ultima.
Costruire un payload #
| Metodo | Ruolo |
|---|---|
of_add_string (string as_path, string as_value) → long | Aggiunge una STRINGA, con escape automatico, all'ARRAY in as_path. L'array deve già esistere: apritelo prima con of_set_raw e un array vuoto. Restituisce 0, -4 se as_path manca o non è un array, -5 se un livello di as_path è un indice 0 su un array; una stringa null si scrive vuota (per un null JSON: of_add_raw(as_path, "null")) |
of_add_boolean (string as_path, boolean ab_value) → long | Aggiunge un BOOLEANO (true o false, mai tra virgolette) all'ARRAY in as_path. L'array deve già esistere: apritelo prima con of_set_raw e un array vuoto. Restituisce 0, -4 se as_path manca o non è un array, -5 se un livello di as_path è un indice 0 su un array; un valore null scrive null |
of_add_number (string as_path, long al_value) → long | Aggiunge un NUMERO (cinque overload: integer, long, longlong, decimal, double — un decimal e un longlong conservano TUTTE le cifre (i centesimi di un importo, l'ultima cifra di un identificativo oltre 2^53), e un letterale come 690.50 è un decimal, scritto 690.5) all'ARRAY in as_path. L'array deve già esistere: apritelo prima con of_set_raw e un array vuoto. Restituisce 0, -4 se as_path manca o non è un array, -5 se un livello di as_path è un indice 0 su un array; un valore null scrive null |
of_add_raw (string as_path, string as_json) → long | Aggiunge un valore GIÀ in JSON (un oggetto, un array) di cui rispondete all'ARRAY in as_path. L'array deve già esistere: apritelo prima con of_set_raw e un array vuoto. Restituisce 0, -4 se as_path manca o non è un array, -5 se un livello di as_path è un indice 0 su un array; un valore null o vuoto scrive null. Il percorso vuoto è la RADICE: of_load("[]") poi of_add_raw("", …) costruisce un documento che è un array (il corpo di una chiamata API a lotti). Aggiungere molti elementi di seguito allo stesso array resta rapido |
of_set_array (string as_path, string as_values[]) → long | SCRIVE un intero ARRAY di stringhe in as_path da un array PowerBuilder, ogni elemento con escape. Un array vuoto ne scrive uno vuoto, un elemento null una stringa vuota. Stessa regola di percorso e stessi codici di of_set_string |
of_set_members (string as_fragment) → long | Unisce alla RADICE membri già formati altrove, uniti da virgole. Una chiave che la radice ha già vede il suo valore sostituito sul posto, una nuova è aggiunta alla fine, una chiave ripetuta dal frammento tiene il suo ultimo valore. Un frammento vuoto non scrive nulla. Restituisce 0, -4 se la radice del documento non è un oggetto |
of_clear ( ) → long | Svuota il documento per iniziare un altro oggetto con la stessa variabile. Restituisce 0 |
of_text ( ) → string | Il documento così com'è (compatto): ciò che hai costruito (of_add_string, of_add_number...) o caricato (of_load), dopo ogni modifica — l'unica uscita, pronta da inviare, memorizzare o riscrivere. of_pretty ne dà la forma indentata. {} se vuoto; chiamarlo non svuota nulla |
Leggere un documento #
| Metodo | Ruolo |
|---|---|
of_load (string as_json) → long | Carica un testo JSON per la lettura. Restituisce 0 se ben formato, -5 se l'argomento è vuoto o solo spazi (spazi, tabulazioni, a capo), -4 se non è JSON valido o annida più di 512 livelli (il documento viene allora scartato). Analizza in PowerScript puro. Un BOM (U+FEFF) in testa, quello di un file salvato in UTF-8 con BOM, viene ignorato. Su un codice negativo, of_get_last_error dice dove il testo è sbagliato (riga, colonna) e of_error_position a quale carattere. Un documento può essere un solo valore ("abc", 42, null): si legge al percorso vuoto, non vi si scrive nulla |
of_is_valid ( ) → boolean | Vero quando l'oggetto contiene un documento: l'ultimo of_load è riuscito, o qualcosa è stato scritto da allora. Un valore passato a of_set_raw / of_add_raw non viene ricontrollato |
of_exists (string as_path) → boolean | Vero quando un valore esiste al percorso dato — distingue un valore presente ma vuoto da uno assente |
of_type (string as_path) → string | Il tipo JSON al percorso: object, array, string, number, boolean, null; vuoto se assente |
of_get_string (string as_path) → string | Il valore al percorso, come testo: una stringa torna decodificata, un numero/booleano/null come testo, un oggetto o array come JSON grezzo (ricaricabile con of_load); una chiave scritta due volte si legge alla sua PRIMA occorrenza |
of_get_number (string as_path) → double | Il numero al percorso, come double — il punto decimale è rispettato su ogni macchina (2.5 è 2,5, non 2). 0 se assente; l'esponente è risolto (1e-7, 2.5E+3) e si conservano 17 cifre significative, zeri iniziali dell'esponente compresi. Per un importo o un identificativo che deve conservare tutte le cifre: of_get_decimal o of_get_longlong. Una stringa conta solo se è interamente un numero JSON: "12.50" vale 12,5, "12 kg" e "1,5" valgono 0 |
of_get_decimal (string as_path) → decimal | Il numero al percorso, come decimal, ricostruito dal TESTO del numero e mai tramite un double: 12345678901234.56 torna con i suoi centesimi, 2.5E-3 vale 0.0025. Al massimo 28 cifre significative. 0 se assente, se il valore non è un numero, o oltre ciò che un decimal contiene; una stringa conta solo se è interamente un numero ("12.50") |
of_get_longlong (string as_path) → longlong | Il numero al percorso, come intero a 64 bit, ricostruito dal suo testo e mai tramite un double: un identificativo di database come 9007199254740993 torna intero. I decimali vengono troncati (2.9 dà 2). 0 se assente, se il valore non è un numero, o fuori dall'intervallo di un longlong; una stringa conta solo se è interamente un numero ("12.50") |
of_get_boolean (string as_path) → boolean | Il booleano al percorso: vero per il letterale JSON true e per la stringa "true" che scrivono alcune API; falso per tutto il resto |
of_count (string as_path) → long | Il numero di membri dell'oggetto, o di elementi dell'array, al percorso. Restituisce -1 se il valore è scalare o assente (distingue un array vuoto, 0, da uno mancante, -1). Con of_name si percorre un oggetto; un array si percorre con il suo indice nel percorso (rows/1, rows/2…). Chiamato a ogni giro di un ciclo, non costa più nulla una volta contato l'array, rimozioni comprese |
of_name (string as_path, long al_index) → string | Il nome del membro n° al_index (da 1) dell'oggetto al percorso — per leggere le chiavi di un oggetto di forma ignota. Con of_count, percorre l'oggetto. Per farne un livello di percorso: of_escape_key (una chiave può contenere un /) |
of_escape_key (string as_key) → string | Una CHIAVE scritta come UN livello di percorso (JSON Pointer, RFC 6901): un ~ diventa ~0, poi un / diventa ~1 — la chiave application/json è il livello application~1json. Ciò che serve a una chiave letta da of_name prima di entrare in un percorso |
of_get_array (string as_path, ref string as_values[]) → long | Tutti gli elementi dell'array al percorso, nell'ordine, in as_values (svuotato prima) — ciascuno come lo legge of_get_string: una stringa torna decodificata, un numero o un booleano come testo, null come "", un oggetto o un array come JSON grezzo (da caricare con of_load in un altro n_pbt_json). "" è la radice. Restituisce il numero di elementi (0 per un array vuoto), -4 quando al percorso non c'è un array (niente, un oggetto, uno scalare), -5 quando un livello del percorso è un indice 0 su un array |
of_pretty ( ) → string | Il documento — caricato o costruito — re-indentato per la lettura (più righe, tabulazioni) — un log, una casella di testo. Vuoto se non ce n'è, o se un valore posto con of_set_raw annida più di 512 livelli (il testo non sarebbe il documento) |
of_pretty (long al_indent) → string | Il documento — caricato o costruito — re-indentato con al_indent spazi per livello (2 e 4 sono le larghezze usuali). 0 lo scrive compatto, su una riga e senza spazi: il testo più piccolo da memorizzare o inviare. Vuoto se non c'è documento, o se al_indent è negativo, superiore a 16 o null, o se un valore posto con of_set_raw annida più di 512 livelli. of_pretty() senza argomento mantiene le tabulazioni |
// 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)
Modificare un documento #
Il lato scrittura cambia il documento caricato sul posto, poi of_text ne rende il risultato (compatto) — ciò che si riscrive. I setter sostituiscono il valore al percorso, o aggiungono l'ultima chiave quando manca a un oggetto padre. Ognuno rende 0, -4 quando un livello del percorso è uno scalare, o un array senza quell'indice, -5 su un percorso vuoto o un indice 0 su un array. Un array incontrato lungo il percorso si attraversa con un indice ESISTENTE (items/1/qty aggiunge qty al primo elemento); si crea sempre e solo una chiave di oggetto. Un valore null (numero, booleano, JSON grezzo vuoto) si scrive null. Un ciclo di scritture, di chiavi aggiunte o di rimozioni in un documento grande (2 000 righe) resta rapido: ogni chiamata rilegge solo ciò che tocca.
| Membro | Ruolo |
|---|---|
of_set_string (string as_path, string as_value) → long | SCRIVE una stringa in as_path, con escape automatico. Il percorso può avere PIÙ livelli (a/b/c): quelli mancanti sono creati come OGGETTI, e un documento VUOTO ne diventa uno — scrivere È costruire. Un valore già presente viene sostituito, ovunque si trovi. Una chiave che contiene un / si scrive ~1 nel percorso (of_escape_key). Un ciclo di scritture in un documento grande resta rapido. Restituisce 0, -4 se un livello del percorso è uno scalare, o un array senza quell'indice (un array si attraversa con un indice esistente: items/1/qty), -5 su un percorso vuoto o un indice 0 su un array. Una stringa null si scrive vuota; per un null JSON: of_set_raw(as_path, "null") |
of_set_number (string as_path, long al_value) → long | SCRIVE un NUMERO in as_path, il punto decimale forzato. Cinque overload: integer, long, longlong, decimal, double — un decimal e un longlong conservano TUTTE le cifre (i centesimi di un importo, l'ultima cifra di un identificativo oltre 2^53), e un letterale come 690.50 è un decimal, scritto 690.5. Stessa regola di percorso e stessi codici di of_set_string; un valore null scrive null |
of_set_boolean (string as_path, boolean ab_value) → long | SCRIVE un BOOLEANO in as_path: true o false, mai tra virgolette. Stessa regola di percorso e stessi codici di of_set_string; un valore null scrive null |
of_set_raw (string as_path, string as_json) → long | SCRIVE in as_path un valore GIÀ in JSON — un oggetto annidato, un array, null — così com'è: ne rispondete voi. È anche così che si APRE un array prima di of_add_*. Stessa regola di percorso e stessi codici di of_set_string; un valore null o vuoto scrive null |
of_remove (string as_path) → long | Rimuove il valore al percorso — un membro di oggetto (la sua chiave e una virgola vanno con esso) o un elemento di array; il risultato resta valido. Restituisce 0, -4 se non c'è nulla, -5 su un percorso vuoto o un indice 0 su 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}
Date #
Una data si scrive e si legge in ISO 8601 — ciò che scrivono le API, i browser e Python —, qualunque sia il formato di data della macchina: una data "2026-10-10", una data-ora "2026-10-10T14:30:00" (la frazione di secondo segue quando non è nulla), un'ora "14:30:00". Un valore null scrive null.
| Metodo | Ruolo |
|---|---|
of_set_date (string as_path, date ad_value) → long | SCRIVE una data in as_path (yyyy-mm-dd). Stessa regola di percorso di of_set_string: restituisce 0, -4 se un livello del percorso è uno scalare o un array senza quell'indice, -5 su un percorso vuoto o un indice 0 su un array |
of_set_datetime (string as_path, datetime adt_value) → long | SCRIVE una data-ora (yyyy-mm-ddThh:mm:ss, la frazione di secondo dopo un punto quando non è nulla). Nessun fuso è scritto: l'ora è quella data. Restituisce 0, -4 o -5, come of_set_date |
of_set_time (string as_path, time at_value) → long | SCRIVE un'ora (hh:mm:ss). Restituisce 0, -4 o -5, come of_set_date |
of_add_date (string as_path, date ad_value) → long | Aggiunge una data all'ARRAY in as_path. Restituisce 0, -4 se as_path manca o non è un array, -5 se un livello di as_path è un indice 0 su un array |
of_add_datetime (string as_path, datetime adt_value) → long | Aggiunge una data-ora all'ARRAY in as_path. Restituisce 0, -4 o -5, come of_add_date |
of_add_time (string as_path, time at_value) → long | Aggiunge un'ora all'ARRAY in as_path. Restituisce 0, -4 o -5, come of_add_date |
of_get_date (string as_path) → date | La data scritta al percorso ("2026-10-10", o la data di una data-ora). 1900-01-01 se il valore è assente, non è una data o indica un giorno che non esiste (2026-02-30); of_exists e of_type distinguono un valore assente |
of_get_datetime (string as_path) → datetime | La data-ora scritta al percorso: una T o uno spazio tra data e ora, con o senza secondi, con una frazione di secondo, o una data sola (mezzanotte). Una Z o uno scarto (+02:00) è letto e non applicato: l'ora è quella scritta — convertitela voi quando il fuso conta. 1900-01-01 00:00:00 se assente o non è una data |
of_get_time (string as_path) → time | L'ora scritta al percorso ("14:30", "14:30:00", "14:30:00.250", o l'ora di una data-ora). 00:00:00 se assente, non è un'ora, o una data 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 in JSON, e ritorno #
PowerBuilder ha ExportJson e ImportJson solo dalla 2017 R2. n_pbt_json lo fa da PowerBuilder 10, tipizzato dalle colonne: una stringa, un numero (un decimal conserva tutte le cifre), una data yyyy-mm-dd, una data-ora, un'ora, null per un NULL. Un overload prende un datawindow, un altro un datawindowchild.
| Metodo | Ruolo |
|---|---|
of_from_datastore (string as_path, datastore ads_source) → long | SCRIVE le righe del buffer primario come un ARRAY di oggetti in as_path: un oggetto per riga, un membro per colonna, chiamato come la colonna. Il percorso vuoto fa del DOCUMENTO quell'array (il corpo di una chiamata a lotti). Restituisce il numero di righe scritte, -5 se il DataStore non è valido o non ha colonne, altrimenti ciò che restituisce of_set_raw |
of_to_datastore (string as_path, datastore ads_target) → long | INSERISCE l'ARRAY di oggetti in as_path in un DataStore: una riga per oggetto, ogni membro nella colonna con lo stesso nome (maiuscole ignorate), convertito al tipo della colonna — un numero da un numero o da una stringa che è interamente un numero, una data, una data-ora o un'ora da un testo ISO, NULL per un null o un valore che la colonna non può contenere. Un membro che non nomina alcuna colonna è ignorato, un elemento che non è un oggetto non fa riga. Le righe sono NUOVE: Update le inserisce. Restituisce il numero di righe inserite, -5 se il DataStore non è valido o non ha colonne, -4 se non c'è un array in 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
Quando il testo non è JSON #
| Metodo | Ruolo |
|---|---|
of_get_last_error ( ) → string | Perché l'ultima chiamata ha restituito un codice negativo; dopo un of_load rifiutato, dove il testo è sbagliato e perché: line 2, column 6 : ':' expected after a key. Vuoto dopo una chiamata riuscita |
of_error_position ( ) → long | Restituisce la posizione, contata da 1 nel testo dato all'ultimo of_load (un BOM compreso), del carattere in cui quel testo diventa sbagliato — da selezionare in un editor; 0 quando l'ultimo of_load è riuscito |
// 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
Ambito. Il JSON si analizza in PowerScript puro, senza pagina né motore:
n_pbt_jsonresta autoinstantiate e funziona ovunque, PowerBuilder 10 incluso. Per l'XML, vedi xml (che si appoggia al motore); per mostrare un JSON come albero comprimibile, vedi jsontree.