How do I process JSON data with stream pipelines in EK9?

← JSON and Data Processing · Ref: Q191

EK9 stream pipelines can extract typed values from JSON using 'collect as Type'. JSON values flow through pipelines and convert to target types automatically.

JSON TO TYPED VALUE

Extract a single typed value from JSON:

  json <- List(JSON("val", JSON(2)))
  anInt <- cat json | collect as Integer

The pipeline extracts the integer value 2.

JSON ARRAY SUMMATION

Convert a list to JSON and sum via pipeline:

  total <- cat $$ [4, 6, 18, 22] | collect as Integer

The $$ converts the list to JSON, pipeline sums as Integer.

JSON OBJECT PROPERTY SUMMATION

Parse a JSON object with JSON().parse(text), which returns a Result of (JSON, String), then sum its numeric properties:

  objectResult <- JSON().parse(`{"a": 1, "b": null, "c": 22}`)
  if objectResult.isOk()
    total <- cat objectResult.ok() | collect as Integer
    stdout.println($total)

The total is 23: null values are skipped (they become unset in the tri-state model). The JSON(String) constructor does NOT parse - it makes a JSON string value, and summing that gives an unset result.

NULL HANDLING

JSON null becomes an unset value in EK9:

  nullParse <- JSON().parse(`{"val": null}`)
  if nullParse.isOk()
    result <- cat List(nullParse.ok()) | collect as Integer
    stdout.println(`unset: ${not result?}`)

See Q188 for JSON basics. See Q59 for function pipelines. See Q122 for collect as.

Example

defines module qa.jsondata.streams

  defines program

    JsonStreamsDemo()
      stdout <- Stdout()

      // === JSON TO TYPED VALUE ===

      json <- List(JSON("mainValue", JSON(2)))
      anInt <- cat json | collect as Integer
      stdout.println(`Extracted integer: ${anInt}`)

      // === JSON ARRAY SUMMATION ===

      sumOfArray <- cat $$ [4, 6, 18, 22] | collect as Integer
      stdout.println(`Sum of array: ${sumOfArray}`)

      // === JSON OBJECT PROPERTY SUMMATION ===
      // parse() returns Result of (JSON, String); the null property is skipped

      objectResult <- JSON().parse(`{"first": 1, "second": null, "third": 22}`)
      if objectResult.isOk()
        jsonObject <- objectResult.ok()
        sumOfProps <- cat jsonObject | collect as Integer
        stdout.println(`Sum of properties: ${sumOfProps}`)

      // === NULL HANDLING ===

      // JSON null becomes unset in EK9's tri-state model
      nullParse <- JSON().parse(`{"mainValue": null}`)
      if nullParse.isOk()
        jsonWithNull <- List(nullParse.ok())
        nullResult <- cat jsonWithNull | collect as Integer
        if not nullResult?
          stdout.println("JSON null became unset Integer")

      // === FLOAT EXTRACTION ===

      jsonFloat <- List(JSON(2.88))
      aFloat <- cat jsonFloat | collect as Float
      stdout.println(`Extracted float: ${aFloat}`)

Common mistakes

E50001 — parse() is an INSTANCE method, not a static one: call it on JSON() - JSON().parse(text) - and it returns a Result of (JSON, String). Check isOk() before ok() (an unguarded ok() is E08030). The JSON(String) constructor does not parse; it makes a JSON string value. See ek9 -h E50001 for details.

Incorrect:

objectResult <- JSON.parse(`{"first": 1, "second": null, "third": 22}`)

Correct:

objectResult <- JSON().parse(`{"first": 1, "second": null, "third": 22}`)
Other ways to ask this
  • How do I extract typed values from JSON using streams?
  • How do I sum JSON values with pipelines in EK9?
  • How does collect as work with JSON in EK9?

Coming from another language?

Java: Jackson + Stream API for JSON processing, manual type extraction. Python: json.loads() + list comprehensions. Rust: serde_json + iterators. Go: json.Unmarshal to struct + range loops. EK9: JSON integrates with stream pipelines natively, 'collect as Type' extracts and aggregates typed values from JSON.

Keywords: sum, json, stream, extract, serialize, data, pipeline, convert, type, collect, aggregate