From 7ece4eb9e6c3e6c9af9994660402d32dd97411a4 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 3 Oct 2025 22:18:58 -0600 Subject: [PATCH] feat(jsonl): add example using encoding/json --- cmd/jsonl/README.md | 128 +++++++++++++++++++++++++++++++++++++++ cmd/jsonl/go.mod | 3 + cmd/jsonl/main.go | 25 ++++++++ cmd/jsonl/messages.jsonl | 3 + 4 files changed, 159 insertions(+) create mode 100644 cmd/jsonl/README.md create mode 100644 cmd/jsonl/go.mod create mode 100644 cmd/jsonl/main.go create mode 100644 cmd/jsonl/messages.jsonl diff --git a/cmd/jsonl/README.md b/cmd/jsonl/README.md new file mode 100644 index 0000000..c593937 --- /dev/null +++ b/cmd/jsonl/README.md @@ -0,0 +1,128 @@ +# JSONL + +An example of using `encoding/json`'s `dec.More()` to read JSONL natively. \ +(because it can read any valid sequence of back-to-back JSON objects) + +```go +package main + +import ( + "encoding/json" + "fmt" + "os" +) + +func main() { + decoder := json.NewDecoder(os.Stdin) + + var err error + for decoder.More() { + var data any + if err = decoder.Decode(&data); err != nil { + break + } + fmt.Printf("Decoded: %#v\n\n", data) + } + if err != nil { + fmt.Fprintf(os.Stderr, "error decoding JSON: %v\n", err) + } + + fmt.Printf("Done\n") +} +``` + +## Strict JSONL + +This will parse strict JSONL. + +`./messages.jsonl`: + +```json5 +{"name":"Alice","age":25} +{"name":"Bob","age":30} +{"name":"Charlie","age":35} +``` + +```text +Decoded: map[string]interface {}{"age":25, "name":"Alice"} + +Decoded: map[string]interface {}{"age":30, "name":"Bob"} + +Decoded: map[string]interface {}{"age":35, "name":"Charlie"} +``` + +## Back-to-back JSON + +It will also parse... anything else. + +`./messages.jsonish`: + +```json5 +null + +true +false + +0 +1 + +"hello" + +[2, 11, 37, 42] + +{"name":"Alice","age":25} +{ + "name":"Bob", + "age":30 +} + + +{ + "name": + "Charlie", + "age": + 35 + } +``` + +```text +Decoded: + +Decoded: true + +Decoded: false + +Decoded: 0 + +Decoded: 1 + +Decoded: "hello" + +Decoded: []interface {}{2, 11, 37, 42} + +Decoded: map[string]interface {}{"age":25, "name":"Alice"} + +Decoded: map[string]interface {}{"age":30, "name":"Bob"} + +Decoded: map[string]interface {}{"age":35, "name":"Charlie"} +``` + +## Non-JSON + +`dec.More()` does not stop after error. You must check the return errors and break out yourself. + +```json5 +{"name":"Alice","age":25} +{"name":"Bob","age":30} +{"name":"Charlie" +``` + +```text +Decoded: map[string]interface {}{"age":25, "name":"Alice"} + +Decoded: map[string]interface {}{"age":30, "name":"Bob"} + +error decoding JSON: unexpected EOF + +Done +``` diff --git a/cmd/jsonl/go.mod b/cmd/jsonl/go.mod new file mode 100644 index 0000000..ac22cac --- /dev/null +++ b/cmd/jsonl/go.mod @@ -0,0 +1,3 @@ +module github.com/therootcompany/golib/cmd/jsonl + +go 1.24.6 diff --git a/cmd/jsonl/main.go b/cmd/jsonl/main.go new file mode 100644 index 0000000..9bb268b --- /dev/null +++ b/cmd/jsonl/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "encoding/json" + "fmt" + "os" +) + +func main() { + decoder := json.NewDecoder(os.Stdin) + + var err error + for decoder.More() { + var data any + if err = decoder.Decode(&data); err != nil { + break + } + fmt.Printf("Decoded: %#v\n\n", data) + } + if err != nil { + fmt.Fprintf(os.Stderr, "error decoding JSON: %v\n\n", err) + } + + fmt.Printf("Done\n") +} diff --git a/cmd/jsonl/messages.jsonl b/cmd/jsonl/messages.jsonl new file mode 100644 index 0000000..b96aa55 --- /dev/null +++ b/cmd/jsonl/messages.jsonl @@ -0,0 +1,3 @@ +{"name":"Alice","age":25} +{"name":"Bob","age":30} +{"name":"Charlie","age":35}