106 / Input, output and data

JSON: exact numbers

json_stringify on a node re-emits the number EXACTLY as it appeared in the source text, extra trailing zeros included. json_as_float instead goes through a double, and then float_to_string returns the minimal form that rounds back to that same double — so 19.90 can come back as 19.9. To show a price with a fixed number of decimals, there is float_to_fixed.

106-json-exact-numbers.nxSource →
// JSON: json_stringify sobre un nodo reemite el número EXACTO tal como vino
// (con sus ceros de más incluidos), a diferencia de json_as_float +
// float_to_string, que pasa por un double y devuelve la forma MÍNIMA que
// vuelve a ese mismo double. float_to_fixed sirve para volver a un ancho
// fijo de decimales (precios).

import "std/json"
import "std/math_ext"

fn main() -> int {
    let doc: String = "{\"precio\": 19.90, \"embedding\": [0.013426971, 0.1]}"
    let parsed: Array = json_parse(doc)

    // El documento completo reemitido: cada número, tal como vino.
    print(json_stringify(parsed))

    let precio_node: Array = json_get(parsed, "precio")
    print(json_stringify(precio_node))          // texto exacto: conserva el cero

    let embedding_node: Array = json_get(parsed, "embedding")
    print(json_stringify(embedding_node))       // literal exacto, sirve para pgvector

    // json_as_float + float_to_string: pasa por un double.
    let precio: float = json_as_float(precio_node)
    print(float_to_string(precio))              // perdió el cero de más

    // Ancho fijo de decimales para mostrar el precio de nuevo:
    print(float_to_fixed(precio, 2))

    return 0
}
Outputstdout
{"precio":19.90,"embedding":[0.013426971,0.1]}
19.90
[0.013426971,0.1]
19.9
19.90

How it works

The whole document re-emitted keeps every number exactly as written: 19.90 stays 19.90, not 19.9. The same happens when re-emitting a single node with json_stringify(precio_node): it is exact text, not a round trip through floating point.

embedding_node shows why this matters beyond aesthetics: an array of high-precision floats — the typical case of an embedding headed for pgvector — needs every digit preserved to avoid losing precision on the round trip.

json_as_float(precio_node) does go through a double, and float_to_string prints the minimal representation that rounds back to the same value: the extra zero is lost. float_to_fixed(precio, 2) gets it back for display, forcing two decimals regardless of what the original JSON carried.