A JSON parser and serializer library for hica. Parses any valid JSON and provides a pipe-friendly API for navigating and extracting values.
hica add json
hica fetchThis records the dependency in hica.hml and downloads the package.
import "json"
- Null:
null - Booleans:
true,false - Numbers: integers (
42,-7) and floats (3.14,-3.14,1e10,1.5e-2)- Integer tokens (no
.or exponent) parse asJIntand emit without a decimal point - Float tokens parse as
JNumberand emit with the shortest round-trip decimal
- Integer tokens (no
- Strings: double-quoted with escape sequences (
\",\\,\n,\r,\t,\uXXXX) - Arrays:
[1, "two", true], nested, trailing whitespace - Objects:
{"key": value}, nested, any JSON value as field value - Whitespace: ignored between tokens
type Json {
JNull,
JBool(value: bool),
JInt(value: int),
JNumber(value: float),
JString(value: string),
JArray(value: list<Json>),
JObject(fields: list<(string, Json)>)
}Use JInt when constructing integer values so they serialise without a decimal point (7 not 7.0). JNumber is for values that are genuinely floating-point.
parse_json(input: string) : result<Json, string>Chain operations with |> or . to navigate nested JSON:
let host = parse_json(input)
|> json_ok
|> at("database")
|> at("host")
|> as_str
// host : maybe<string>Hica supports Uniform Function Call Syntax (UFCS), so you can also write:
let host = parse_json(input)
.json_ok
.at("database")
.at("host")
.as_str| Function | Signature | Purpose |
|---|---|---|
json_ok |
result<Json, string> -> maybe<Json> |
Convert parse result to maybe |
at |
maybe<Json>, string -> maybe<Json> |
Navigate into an object field |
nth |
maybe<Json>, int -> maybe<Json> |
Index into an array |
as_str |
maybe<Json> -> maybe<string> |
Extract string value |
as_int |
maybe<Json> -> maybe<int> |
Extract int value (truncates float) |
as_num |
maybe<Json> -> maybe<float> |
Extract number as float |
as_bool |
maybe<Json> -> maybe<bool> |
Extract bool value |
as_array |
maybe<Json> -> maybe<list<Json>> |
Extract array items |
as_object |
maybe<Json> -> maybe<list<(string, Json)>> |
Extract object fields |
let port = parse_json(input)
|> json_ok
|> at("server")
|> at("port")
let p = int_or(port, 8080)| Function | Signature |
|---|---|
str_or |
maybe<Json>, string -> string |
int_or |
maybe<Json>, int -> int |
num_or |
maybe<Json>, float -> float |
bool_or |
maybe<Json>, bool -> bool |
| Function | Signature | Purpose |
|---|---|---|
has_key |
maybe<Json>, string -> bool |
Check if object has field |
keys |
maybe<Json> -> list<string> |
Get object field names |
json_length |
maybe<Json> -> int |
Count array items or object fields |
For when you already have a Json value (not wrapped in maybe):
| Function | Signature |
|---|---|
json_get |
Json, string -> maybe<Json> |
json_str |
Json -> maybe<string> |
json_int |
Json -> maybe<int> |
json_num |
Json -> maybe<float> |
json_bool |
Json -> maybe<bool> |
json_array |
Json -> maybe<list<Json>> |
json_object |
Json -> maybe<list<(string, Json)>> |
json_is_null |
Json -> bool |
json_show(j: Json) : string // compact one-line (type summary for containers)
json_pretty(j: Json, indent: int) : string // indented multi-line outputEmit compact JSON from Json values:
json_emit(j: Json) : string // compact single-line JSONExample:
let data = JObject([("name", JString("myapp")), ("port", JInt(8080))])
println(json_emit(data))
// {"name": "myapp", "port": 8080}
println(json_pretty(data, 0))
// {
// "name": "myapp",
// "port": 8080
// }The two core patterns when combining JSON with the hica HTTP library:
GET → parse → navigate
extern import "http"
import "./lib/json/src/json"
let resp = http_get("https://api.example.com/users/1")
match parse_json(resp.body) {
Ok(doc) => {
let name = Some(doc) |> at("name") |> as_str
println(str_or(name, "<no name>"))
},
Err(e) => println("error: " + e)
}Build JSON → json_emit → POST
let payload = JObject([
("name", JString("Alice")),
("age", JInt(30)),
("admin", JBool(false))
])
let post_resp = http_post(
"https://api.example.com/users",
json_emit(payload),
content_type="application/json"
)
println("Status: " + show(post_resp.status))See examples/http_json.hc for a full working example with both patterns.
See the examples/ directory for runnable programs:
- basic_parsing.hc: Parse a JSON string and pretty-print it
- pipe_navigation.hc: Navigate nested values, use defaults, inspect structure
- http_json.hc: GET a JSON API and POST a JSON body (requires hica HTTP library)
Run an example:
hica run examples/basic_parsing.hc