JSON and CSV
Use format modules to parse data, inspect it, validate it, and encode output.
Parse
json.parse_json and csv.parse_csv turn text into structured values.
parsed: Result[JsonValue, String] = parse_json(text)
Inspect
JSON accessors return Option so missing fields stay explicit.
name: Option[String] = value
.get_field("name")
.and_then(func(v): v.as_string())
Validate
A pure field decoder returns Result[String, String]. Missing name and a wrong field type are different failures; an explicitly empty string is still a string.
import:
json: JsonValue, as_string, get_field, parse_json
pure func user_name(value: JsonValue) -> Result[String, String]:
field ?= value.get_field("name").to_result("missing name")
field.as_string().to_result("expected a string")
func main(args: List[String]) -> Int:
text: String = args.get(1).get_or("{\"name\":\"Ada\"}")
result: Result[String, String] = parse_json(text).and_then(user_name)
match result:
Ok(name):
print(name) -- default output: Ada
0
Err(message):
print_error(message) -- {}: missing name; {"name":42}: expected a string
1
Encode
CSV rows can be formatted back into text.
csv_text: String = format_csv([["name"], ["Ada"]])
Example
Require a JSON array and a string name on every user. Reject the whole conversion on the first invalid user, print the error to stderr, and exit with status 1 -- never silently substitute a blank field. An empty array produces just the header. The optional first argument supplies JSON; otherwise the built-in Ada example is used.
import:
csv: format_csv
json: JsonValue(JsonVector), as_string, get_field, parse_json
pure func user_name(value: JsonValue) -> Result[String, String]:
field ?= value.get_field("name").to_result("missing name")
field.as_string().to_result("expected a string")
-- Reject the entire input on the first invalid user; never invent a blank name.
pure func users_csv(text: String) -> Result[String, String]:
match parse_json(text):
Ok(JsonVector(users)):
var rows: Result[List[List[String]], String] = Ok([["name"]])
for user in users:
match rows:
Ok(validated):
rows = match user_name(user):
Ok(name): Ok(validated.append([name]))
Err(message): Err(message)
Err(_): break
rows.map(format_csv)
Ok(_): Err("expected array")
Err(message): Err(message)
func main(args: List[String]) -> Int:
text: String = args.get(1).get_or("[{\"name\":\"Ada\"}]")
match users_csv(text):
Ok(csv_text):
print(csv_text) -- default output bytes: name\r\nAda\n
0
Err(message):
print_error(message) -- {}: expected array; [{}]: missing name; [{"name":42}]: expected a string
1
Try it
blorp run users-csv.brp