Skip to content

JSON typed accessors: json_as_string, json_get_number, etc. #366

@aallan

Description

@aallan

Problem

Working with JSON API responses in Vera requires a two-level pattern match every time you want a typed value out of an object field. From a real HTTP+JSON program:

private fn extract_float(@Option<Json> -> @String)
  effects(pure)
{
  match @Option<Json>.0 {
    None -> "N/A",
    Some(@Json) -> match @Json.0 { JNumber(@Float64) -> float_to_string(@Float64.0), _ -> "N/A" }
  }
}

This pattern — unwrap the Option, then match the Json constructor — is boilerplate that every JSON API consumer will write, differing only in which constructor (JNumber, JString, JBool) they match on. The current stdlib (json_get returning Option<Json>) gives you the field, but leaves the last mile to the user.

Proposed additions

Layer 1 — type coercion accessors (Json → Option):

json_as_string(@Json.0)   -- Option<String>   — Some if JString, None otherwise
json_as_number(@Json.0)   -- Option<Float64>  — Some if JNumber, None otherwise
json_as_bool(@Json.0)     -- Option<Bool>     — Some if JBool,   None otherwise
json_as_int(@Json.0)      -- Option<Int>      — Some if JNumber (applies float_to_int), None otherwise
json_as_array(@Json.0)    -- Option<Array<Json>>        — Some if JArray, None otherwise
json_as_object(@Json.0)   -- Option<Map<String, Json>>  — Some if JObject, None otherwise

Layer 2 — compound field accessors (Json, String → Option):

json_get_string(@Json.0, "key")   -- Option<String>
json_get_number(@Json.0, "key")   -- Option<Float64>
json_get_bool(@Json.0, "key")     -- Option<Bool>
json_get_int(@Json.0, "key")      -- Option<Int>
json_get_array(@Json.0, "key")    -- Option<Array<Json>>

These are json_get + the corresponding json_as_* composed — which is what 90% of real API-consuming code actually wants.

Impact

The display_weather function from a real Cambridge weather API client shrinks from five dedicated helper functions (each wrapping the two-level match) to five single-line field extractions. Composable with existing Option combinators (option_map, option_unwrap_or).

Implementation

Pure Vera prelude functions — no new WASM host imports required. Each json_as_* is a single match expression; each json_get_* chains json_get + option_flat_map + json_as_*.

Naming

json_as_* follows the coercion-without-panic convention (Rust's .as_str(), Swift's optional casts). json_get_* mirrors the compound-accessor pattern common in config-reading libraries.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions