json — n_pbt_json #
← Referência dos componentes · Índice do guia
Construir um JSON tipo a tipo — texto, número, booleano, array, objeto aninhado — com o escape feito por si, e depois ler um ao longo de um caminho:
of_load,of_get_string,of_type,of_count. Um único objeto constrói os seus pedidos e lê as suas respostas. Tudo em PowerScript puro: sem página, sem motor, PowerBuilder 10 incluído.
▶ Ver ao vivo — Aplicação de demonstração, mosaico JSON: os resultados, o código que os produz e esta página, lado a lado.
Em resumo #
n_pbt_json é autoinstantiate: declara-se como variável local, sem create nem destroy. É o mesmo objeto que, internamente, constrói os payloads enviados ao motor — agora oferecido ao seu código, do lado da construção e da leitura.
Início rápido #
Construir um payload, depois reler uma resposta — tudo cabe numa variável 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
Um caminho são as chaves desde a raiz unidas por /; o índice de um array é a sua posição, contada a partir de 1, como toda a posição da biblioteca: order/lines/1 é a primeira linha, order/lines/0 não designa nada — uma escrita recusa-o com -5. Um nível escreve-se como o escreve o JSON Pointer (RFC 6901): ~1 é um / da chave e ~0 um ~ (paths/~1users lê a chave /users; of_escape_key converte uma chave), um nível vazio é a chave "" (a//b), e um caminho pode começar por / — a forma completa do ponteiro, a única maneira de nomear a chave "" da raiz (/). Se um objeto escrever a mesma chave duas vezes, é a sua PRIMEIRA ocorrência que é lida e escrita — um navegador guarda a última.
Construir um payload #
| Método | Função |
|---|---|
of_add_string (string as_path, string as_value) → long | Acrescenta uma CADEIA, com escape automático, ao ARRAY em as_path. O array tem de existir: abra-o primeiro com of_set_raw e um array vazio. Devolve 0, -4 se as_path faltar ou não for um array, -5 se um nível de as_path for um índice 0 num array; uma cadeia nula escreve-se vazia (para um null JSON: of_add_raw(as_path, "null")) |
of_add_boolean (string as_path, boolean ab_value) → long | Acrescenta um BOOLEANO (true ou false, nunca entre aspas) ao ARRAY em as_path. O array tem de existir: abra-o primeiro com of_set_raw e um array vazio. Devolve 0, -4 se as_path faltar ou não for um array, -5 se um nível de as_path for um índice 0 num array; um valor nulo escreve null |
of_add_number (string as_path, long al_value) → long | Acrescenta um NÚMERO (cinco sobrecargas: integer, long, longlong, decimal, double — um decimal e um longlong mantêm TODOS os algarismos (os cêntimos de um montante, o último algarismo de um identificador acima de 2^53), e um literal como 690.50 é um decimal, escrito 690.5) ao ARRAY em as_path. O array tem de existir: abra-o primeiro com of_set_raw e um array vazio. Devolve 0, -4 se as_path faltar ou não for um array, -5 se um nível de as_path for um índice 0 num array; um valor nulo escreve null |
of_add_raw (string as_path, string as_json) → long | Acrescenta um valor JÁ em JSON (um objeto, um array) pelo qual responde ao ARRAY em as_path. O array tem de existir: abra-o primeiro com of_set_raw e um array vazio. Devolve 0, -4 se as_path faltar ou não for um array, -5 se um nível de as_path for um índice 0 num array; um valor nulo ou vazio escreve null. O caminho vazio é a RAIZ: of_load("[]") e depois of_add_raw("", …) constrói um documento que é um array (o corpo de uma chamada de API em lote). Acrescentar muitos elementos seguidos ao mesmo array continua rápido |
of_set_array (string as_path, string as_values[]) → long | ESCREVE um ARRAY inteiro de cadeias em as_path a partir de um array PowerBuilder, cada elemento com escape. Um array vazio escreve um vazio, um elemento nulo uma cadeia vazia. Mesma regra de caminho e mesmos códigos que of_set_string |
of_set_members (string as_fragment) → long | Funde na RAIZ membros já formados noutro lado, unidos por vírgulas. Uma chave que a raiz já tem vê o seu valor substituído no lugar, uma nova é acrescentada no fim, uma chave que o fragmento repete mantém o seu último valor. Um fragmento vazio não escreve nada. Devolve 0, -4 se a raiz do documento não for um objeto |
of_clear ( ) → long | Esvazia o documento para começar outro objeto com a mesma variável. Devolve 0 |
of_text ( ) → string | O documento tal como está (compacto): o que construiu (of_add_string, of_add_number...) ou carregou (of_load), após qualquer alteração — a saída única, pronta a enviar, guardar ou reescrever. of_pretty dá a forma indentada. {} se vazio; chamá-lo não esvazia nada |
Ler um documento #
| Método | Função |
|---|---|
of_load (string as_json) → long | Carrega um texto JSON para leitura. Devolve 0 se bem formado, -5 se o argumento estiver vazio ou em branco (espaços, tabulações, quebras de linha), -4 se não for JSON válido ou aninhar mais de 512 níveis (o documento é então descartado). Analisa em PowerScript puro. Um BOM (U+FEFF) no início, o de um ficheiro guardado em UTF-8 com BOM, é ignorado. Num código negativo, of_get_last_error diz onde o texto está errado (linha, coluna) e of_error_position em que carácter. Um documento pode ser um só valor ("abc", 42, null): lê-se no caminho vazio, nada se escreve nele |
of_is_valid ( ) → boolean | Verdadeiro quando o objeto contém um documento: o último of_load teve êxito, ou algo foi escrito desde então. Um valor passado a of_set_raw / of_add_raw não é reverificado |
of_exists (string as_path) → boolean | Verdadeiro quando existe um valor no caminho dado — distingue um valor presente mas vazio de um ausente |
of_type (string as_path) → string | O tipo JSON no caminho: object, array, string, number, boolean, null; vazio se ausente |
of_get_string (string as_path) → string | O valor no caminho, como texto: uma string volta descodificada, um número/booleano/null como texto, um objeto ou array como JSON em bruto (recarregável com of_load); uma chave escrita duas vezes lê-se na sua PRIMEIRA ocorrência |
of_get_number (string as_path) → double | O número no caminho, como double — o ponto decimal é respeitado em qualquer máquina (2.5 é 2,5, não 2). 0 se ausente; o expoente é resolvido (1e-7, 2.5E+3) e mantêm-se 17 algarismos significativos, zeros iniciais do expoente incluídos. Para um montante ou um identificador que deve manter todos os algarismos: of_get_decimal ou of_get_longlong. Uma cadeia só conta se for inteiramente um número JSON: "12.50" vale 12,5, "12 kg" e "1,5" valem 0 |
of_get_decimal (string as_path) → decimal | O número no caminho, como decimal, reconstruído a partir do TEXTO do número e nunca através de um double: 12345678901234.56 volta com os seus cêntimos, 2.5E-3 vale 0.0025. No máximo 28 algarismos significativos. 0 se ausente, se o valor não for um número, ou além do que um decimal comporta; uma cadeia só conta se for inteiramente um número ("12.50") |
of_get_longlong (string as_path) → longlong | O número no caminho, como inteiro de 64 bits, reconstruído a partir do seu texto e nunca através de um double: um identificador de base de dados como 9007199254740993 volta inteiro. As casas decimais são cortadas (2.9 dá 2). 0 se ausente, se o valor não for um número, ou fora do intervalo de um longlong; uma cadeia só conta se for inteiramente um número ("12.50") |
of_get_boolean (string as_path) → boolean | O booleano no caminho: verdadeiro para o literal JSON true e para a cadeia "true" que algumas API escrevem; falso para tudo o resto |
of_count (string as_path) → long | O número de membros do objeto, ou de elementos do array, no caminho. Devolve -1 se o valor for escalar ou ausente (distingue um array vazio, 0, de um em falta, -1). Com of_name percorre-se um objeto; um array percorre-se pelo seu índice no caminho (rows/1, rows/2…). Chamado em cada volta de um ciclo, já não custa nada uma vez contado o array, remoções incluídas |
of_name (string as_path, long al_index) → string | O nome do membro n.º al_index (a partir de 1) do objeto no caminho — para ler as chaves de um objeto de forma desconhecida. Com of_count, percorre o objeto. Para fazer dele um nível de caminho: of_escape_key (uma chave pode conter um /) |
of_escape_key (string as_key) → string | Uma CHAVE escrita como UM nível de caminho (JSON Pointer, RFC 6901): um ~ torna-se ~0, depois um / torna-se ~1 — a chave application/json é o nível application~1json. O que uma chave lida por of_name precisa antes de entrar num caminho |
of_get_array (string as_path, ref string as_values[]) → long | Todos os elementos do array no caminho, por ordem, em as_values (esvaziado antes) — cada um como of_get_string o lê: uma string volta descodificada, um número ou um booleano como texto, null como "", um objeto ou um array como JSON em bruto (a carregar com of_load noutro n_pbt_json). "" é a raiz. Devolve o número de elementos (0 para um array vazio), -4 quando não há um array no caminho (nada, um objeto, um escalar), -5 quando um nível do caminho é um índice 0 num array |
of_pretty ( ) → string | O documento — carregado ou construído — reindentado para leitura (várias linhas, tabulações) — um log, uma caixa de texto. Vazio se não houver nenhum, ou se um valor posto com of_set_raw aninhar mais de 512 níveis (o texto não seria o documento) |
of_pretty (long al_indent) → string | O documento — carregado ou construído — reindentado com al_indent espaços por nível (2 e 4 são as larguras habituais). 0 escreve-o compacto, numa linha e sem espaços: o texto mais pequeno para guardar ou enviar. Vazio se não houver documento, ou se al_indent for negativo, superior a 16 ou null, ou se um valor posto com of_set_raw aninhar mais de 512 níveis. of_pretty() sem argumento mantém as tabulações |
// 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 um documento #
O lado de escrita altera o documento carregado no lugar, depois of_text devolve o resultado (compacto) — o que se reescreve. Os setters substituem o valor no caminho, ou acrescentam a última chave quando falta a um objeto pai. Cada um devolve 0, -4 quando um nível do caminho é um escalar, ou um array sem esse índice, -5 num caminho vazio ou um índice 0 num array. Um array encontrado no caminho atravessa-se por um índice que EXISTE (items/1/qty acrescenta qty ao primeiro elemento); só uma chave de objeto é criada. Um valor null (número, booleano, JSON em bruto vazio) escreve-se null. Um ciclo de escritas, de chaves acrescentadas ou de remoções num documento grande (2 000 linhas) continua rápido: cada chamada só relê o que toca.
| Membro | Função |
|---|---|
of_set_string (string as_path, string as_value) → long | ESCREVE uma cadeia em as_path, com escape automático. O caminho pode ter VÁRIOS níveis (a/b/c): os que faltam são criados como OBJETOS, e um documento VAZIO passa a sê-lo — escrever É construir. Um valor já presente é substituído, onde quer que esteja. Uma chave que contém um / escreve-se ~1 no caminho (of_escape_key). Um ciclo de escritas num documento grande continua rápido. Devolve 0, -4 se um nível do caminho for um escalar, ou um array sem esse índice (um array atravessa-se por um índice existente: items/1/qty), -5 com um caminho vazio ou um índice 0 num array. Uma cadeia nula escreve-se vazia; para um null JSON: of_set_raw(as_path, "null") |
of_set_number (string as_path, long al_value) → long | ESCREVE um NÚMERO em as_path, o ponto decimal forçado. Cinco sobrecargas: integer, long, longlong, decimal, double — um decimal e um longlong mantêm TODOS os algarismos (os cêntimos de um montante, o último algarismo de um identificador acima de 2^53), e um literal como 690.50 é um decimal, escrito 690.5. Mesma regra de caminho e mesmos códigos que of_set_string; um valor nulo escreve null |
of_set_boolean (string as_path, boolean ab_value) → long | ESCREVE um BOOLEANO em as_path: true ou false, nunca entre aspas. Mesma regra de caminho e mesmos códigos que of_set_string; um valor nulo escreve null |
of_set_raw (string as_path, string as_json) → long | ESCREVE em as_path um valor JÁ em JSON — um objeto aninhado, um array, null — tal como está: responde por ele. É também assim que se ABRE um array antes de of_add_*. Mesma regra de caminho e mesmos códigos que of_set_string; um valor nulo ou vazio escreve null |
of_remove (string as_path) → long | Remove o valor no caminho — um membro de objeto (a sua chave e uma vírgula vão com ele) ou um elemento de array; o resultado permanece válido. Devolve 0, -4 se nada estiver lá, -5 com um caminho vazio ou um índice 0 num 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}
Datas #
Uma data escreve-se e lê-se em ISO 8601 — o que escrevem as API, os navegadores e o Python —, seja qual for o formato de data da máquina: uma data "2026-10-10", uma data-hora "2026-10-10T14:30:00" (a fração de segundo segue quando não é nula), uma hora "14:30:00". Um valor nulo escreve null.
| Método | Função |
|---|---|
of_set_date (string as_path, date ad_value) → long | ESCREVE uma data em as_path (yyyy-mm-dd). A mesma regra de caminho que of_set_string: devolve 0, -4 se um nível do caminho for um escalar ou um array sem esse índice, -5 com um caminho vazio ou um índice 0 num array |
of_set_datetime (string as_path, datetime adt_value) → long | ESCREVE uma data-hora (yyyy-mm-ddThh:mm:ss, a fração de segundo após um ponto quando não é nula). Nenhum fuso é escrito: a hora é a dada. Devolve 0, -4 ou -5, como of_set_date |
of_set_time (string as_path, time at_value) → long | ESCREVE uma hora (hh:mm:ss). Devolve 0, -4 ou -5, como of_set_date |
of_add_date (string as_path, date ad_value) → long | Acrescenta uma data ao ARRAY em as_path. Devolve 0, -4 se as_path faltar ou não for um array, -5 se um nível de as_path for um índice 0 num array |
of_add_datetime (string as_path, datetime adt_value) → long | Acrescenta uma data-hora ao ARRAY em as_path. Devolve 0, -4 ou -5, como of_add_date |
of_add_time (string as_path, time at_value) → long | Acrescenta uma hora ao ARRAY em as_path. Devolve 0, -4 ou -5, como of_add_date |
of_get_date (string as_path) → date | A data escrita no caminho ("2026-10-10", ou a data de uma data-hora). 1900-01-01 se o valor faltar, não for uma data ou indicar um dia que não existe (2026-02-30); of_exists e of_type distinguem um valor ausente |
of_get_datetime (string as_path) → datetime | A data-hora escrita no caminho: um T ou um espaço entre data e hora, com ou sem segundos, com fração de segundo, ou uma data só (meia-noite). Um Z ou um desvio (+02:00) é lido e não aplicado: a hora é a escrita — converta-a quando o fuso importa. 1900-01-01 00:00:00 se faltar ou não for uma data |
of_get_time (string as_path) → time | A hora escrita no caminho ("14:30", "14:30:00", "14:30:00.250", ou a hora de uma data-hora). 00:00:00 se faltar, não for uma hora, ou uma data só |
// 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")
Um DataStore em JSON, e volta #
O PowerBuilder só tem ExportJson e ImportJson a partir da 2017 R2. n_pbt_json fá-lo desde o PowerBuilder 10, tipado pelas colunas: uma cadeia, um número (um decimal mantém todos os algarismos), uma data yyyy-mm-dd, uma data-hora, uma hora, null para um NULL. Uma sobrecarga recebe um datawindow, outra um datawindowchild.
| Método | Função |
|---|---|
of_from_datastore (string as_path, datastore ads_source) → long | ESCREVE as linhas do buffer principal como um ARRAY de objetos em as_path: um objeto por linha, um membro por coluna, com o nome da coluna. O caminho vazio faz do DOCUMENTO esse array (o corpo de uma chamada em lote). Devolve o número de linhas escritas, -5 se o DataStore não for válido ou não tiver colunas, senão o que devolve of_set_raw |
of_to_datastore (string as_path, datastore ads_target) → long | INSERE o ARRAY de objetos em as_path num DataStore: uma linha por objeto, cada membro na coluna com o mesmo nome (maiúsculas ignoradas), convertido para o tipo da coluna — um número a partir de um número ou de uma cadeia que é inteiramente um número, uma data, uma data-hora ou uma hora a partir de um texto ISO, NULL para um null ou um valor que a coluna não pode conter. Um membro que não nomeia nenhuma coluna é ignorado, um elemento que não é um objeto não faz linha. As linhas são NOVAS: Update insere-as. Devolve o número de linhas inseridas, -5 se o DataStore não for válido ou não tiver colunas, -4 se não houver array em 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 o texto não é JSON #
| Método | Função |
|---|---|
of_get_last_error ( ) → string | Porque é que a última chamada devolveu um código negativo; após um of_load recusado, onde o texto está errado e porquê: line 2, column 6 : ':' expected after a key. Vazio após uma chamada bem-sucedida |
of_error_position ( ) → long | Devolve a posição, contada a partir de 1 no texto dado ao último of_load (um BOM incluído), do carácter onde esse texto fica errado — para selecionar num editor; 0 quando o último of_load foi bem-sucedido |
// 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
Âmbito. O JSON analisa-se em PowerScript puro, sem página nem motor:
n_pbt_jsoncontinua autoinstantiate e funciona em todo o lado, PowerBuilder 10 incluído. Para XML, veja xml (que assenta no motor); para mostrar um JSON como árvore recolhível, veja jsontree.