Skip to content

Conversation

@arnetheduck
Copy link
Member

@arnetheduck arnetheduck commented Jun 27, 2025

An implementation of
#112 that introduces beginArray/endArray for the streaming creation of arrays.

In order to accomodate the need for intra-element plumbing, we add begin/end marker calls to the writeValue implementation which helps the writer keep track of each value being written and therefore allows it to inject the correct delimiters and indents.

Here's an example of writing a writeValue overload that writes an array nested in an object:

# Fully expanded form
proc writeValue(w: var JsonWriter, t: MyType) =
  w.beginArray()

  for i in 0 ..< t.children:
    writer.beginObject(MyType)

    writer.writeName("id")
    writer.writeValue(i)

    writer.writeName("name")
    writer.writeValue("item" & t.childName[i])

    writer.endObject()

  writer.endArray()

# Convenience form
proc writeValue(w: var JsonWriter, t: MyType) =
  w.writeArray:
    for i in 0 ..< t.children:
      writer.writeObject(MyType):
        writer.writeMember("id", i)
        writer.writeMember("name", "item" & t.childName[i])

Similar to the existing beginRecord/endRecord fields we add beginArray and endArray - we also take the opportunity to name beginObject according to its json-spec-derived name. The old name remains available.

This change introduces a compile-time backwards-compatibility break for custom writers that try to access the stream directly: they now have to delimit their value writing with w.streamElement(s): s.write ... where s is the stream variable. The block template enforces begin/end markers on behalf of the writer.

Further examples are available in the documentation.

With this change, we also deprecate workarounds like fieldWritten and endRecordField since a regular replacement exists in the form of consistent begin/end pairs.

An implementation of
#112 that
introduces `beginArray`/`endArray` for the streaming creation of arrays.

In order to accomodate the need for intra-element plumbing, we add
`begin`/`end` marker calls to the `writeValue` implementation which
helps the writer keep track of each value being written and therefore
allows it to inject the correct delimiters and indents.

Here's an example of writing a `writeValue` overload that writes an
array nested in an object:

```nim
proc writeValue(w: var JsonWriter, t: MyType) =
  w.beginArray()

  for i in 0 ..< t.children:
    writer.beginObject()

    writer.writeMember("id", i)
    writer.writeMember("name", "item" & t.childName[i])

    writer.endObject()

  writer.endArray()
```

Similar to the existing `beginRecord`/`endRecord` fields we add
`beginArray` and `endArray` - we also take the opportunity to name
`beginObject` according to its json-spec-derived name. The old name
remains available.

This change introduces a backwards-compatibility break for custom
writers that try to access the stream directly: they now have to delimit
their value writing with `w.streamElement(s): s.write ...` where `s` is
the stream variable. The block template enforces begin/end markers on
behalf of the writer.

Further examples are available in the documentation.

With this change, we also deprecate workarounds like `fieldWritten` and
`endRecordField` since a regular replacement exists in the form of
consistent begin/end pairs.
@arnetheduck arnetheduck mentioned this pull request Jul 2, 2025
@arnetheduck arnetheduck marked this pull request as ready for review July 2, 2025 06:50
Should not be called directly as `writeValue` / `streamElement` take
care of it.
@arnetheduck arnetheduck merged commit bc49ad8 into master Jul 4, 2025
26 checks passed
@arnetheduck arnetheduck deleted the lean-arrays branch July 4, 2025 08:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant