json

Faz parse de texto JSON para valores Bern e serializa valores Bern de volta para JSON.

import json

Mapeamento de valores

Os valores JSON mapeiam para valores Bern assim:

JSONValor Bern
objectObject (#{ ... }#)
arrayList ([ ... ]) - ordem e duplicatas preservadas
stringstring
numberInteger (sem fração/expoente) ou Double
true / falseBoolean
nullUndefined

Um array JSON mapeia diretamente para uma List Bern, mantendo a ordem e as duplicatas dos elementos. Arrays JSON são heterogêneos (ex.: [1, "a", 34.2]); a biblioteca habilita o pragma impure-lists internamente para que suas próprias listas possam conter tipos mistos. Esse pragma é restrito ao arquivo - nunca vaza para o programa que importa json.

json_parse("[1, \"a\", 34.2, \"a\", \"banana\"]")
-- Saída: [1, "a", 34.2, "a", "banana"]
Ressalva de ida e volta: uma string Bern é, ela mesma, uma List de Characters, então uma lista vazia e uma string vazia são indistinguíveis. Um array JSON vazio, portanto, serializa de volta como "". Esse é o único caso de borda; arrays e strings não vazios sempre se distinguem pelo tipo do elemento.

Parsing

json_parse(texto) → valor

Faz parse de um documento JSON em um valor Bern.

person = json_parse("{\"name\": \"Bern\", \"version\": 3}")
person["name"]
-- Saída: "Bern"
person["version"]
-- Saída: 3
nums = json_parse("[10, 20, 30]")
nums[1]
-- Saída: 20

Trabalhando com null

is_null(valor) → booleano

Testa se um valor é um null JSON parseado (ou seja, Undefined).

is_null(json_parse("null"))
-- Saída: true

doc = json_parse("{\"middle_name\": null}")
is_null(doc["middle_name"])
-- Saída: true

Serialização

json_stringify(valor) → string

Serializa um valor Bern em uma string JSON. Os campos de objeto são enumerados com o keys() embutido; listas e conjuntos viram arrays.

json_stringify(#{ items: [1, 2, 3], ok: true }#)
-- Saída: {"items":[1,2,3],"ok":true}

json_stringify(json_parse("[7, 7, 7]"))
-- Saída: [7,7,7]

Juntando tudo

Fazer parse, editar e re-serializar é o fluxo do dia a dia. Aqui lemos uma config, incrementamos um valor e a escrevemos de volta:

Ida e volta de um objeto de config

import json

raw = "{\"name\": \"bern\", \"version\": 2, \"tags\": [\"lang\", \"fun\"]}"

config = json_parse(raw)
config["version"] = config["version"] + 1
config["tags"] = config["tags"] <> ["docs"]

json_stringify(config)
-- Saída: {"name":"bern","version":3,"tags":["lang","fun","docs"]}

E combinando com o core para resumir um array de registros:

Somando valores de um array JSON

import core
import json

data = json_parse("[{\"price\": 12}, {\"price\": 40}, {\"price\": 8}]")

total = data
    )| map(\row -> row["price"])
    )| sum

total
-- Saída: 60