Skip to content

Conversation

@arnetheduck
Copy link
Member

@arnetheduck arnetheduck commented Jun 27, 2025

An implementation of
#112 that
introduces a rich set of helpers for creating arrays using a
backwards-compatible approach that maintains the current semantic model
of the array/object writer being responsible for introducing plumbing.

Since the "outer" level drives the plumbing, we add writers for every
combination of value and context: beginArray, beginArrayElement and
beginArrayMember for creating an array in top-level, array and object
respectively and the same for other values.

In this model, writeValue itself performs no begin/end tracking -
instead, it is up to the entity that creates the array/object to do so
(writeRecordValue, stepwiseArrayCreation and so on).

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

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

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

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

    writer.endObjectElement()

  writer.endArray()

The writing API is quite regular but requires calling special functions
depending on the context which is easy to forget - calling the wrong
variation results in invalid JSON!

The backwards-compatiblity issue can be seen in a new test case based on
a real-world example for writing byte arrays as hex strings.

Further examples are available in the documentation.

An implementation of
#112 that
introduces a rich set of helpers for creating arrays using a
backwards-compatible approach that maintains the current semantic model
of the array/object writer being responsible for introducing plumbing.

Since the "outer" level drives the plumbing, we add writers for every
combination of value and context: `beginArray`, `beginArrayElement` and
`beginArrayMember` for creating an array in top-level, array and object
respectively and the same for other values.

In this model, `writeValue` itself performs no begin/end tracking -
instead, it is up to the entity that creates the array/object to do so
(`writeRecordValue`, `stepwiseArrayCreation` and so on).

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.beginObjectElement()

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

    writer.endObjectElement()

  writer.endArray()
```

The writing API is quite regular but requires calling special functions
depending on the context which is easy to forget - calling the wrong
variation results in invalid JSON!

The backwards-compatiblity issue can be seen in a new test case based on
a real-world example for writing byte arrays as hex strings.

Further examples are available in the documentation.
@arnetheduck
Copy link
Member Author

Closing in favor or #115

@arnetheduck arnetheduck closed this Jul 2, 2025
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