The changes are best explained with an example of how they affect writing nested objects/arrays vs what it's like to access the inner stream:
# nesting
writer.writeObject:
writer.writeMember("status", "ok")
writer.writeArrayMember("data"):
for i in 0 ..< 2:
writer.writeObjectElement:
writer.writeMember("id", i)
writer.writeMember("name", "item" & $i)
# custom serialization directly to stream:
proc writeValue(w: var JsonWriter[StringyJson], value: seq[byte]) =
w.stream.write('"')
w.stream.write(toHex(value))
w.stream.write('"')
vs
# nesting
writer.writeObject:
writer.writeMember("status", "ok")
writer.writeName("data")
writer.writeArray:
for i in 0 ..< 2:
writer.writeObject:
writer.writeMember("id", i)
writer.writeMember("name", "item" & $i)
# direct stream access:
proc writeValue(w: var JsonWriter[StringyJson], value: seq[byte]) =
w.streamElement(s):
s.write('"')
s.write(toHex(value))
s.write('"')
Because the inner stream becomes protected in the latter version, we can catch any breakage at compile-time which is nice. Leaning towards this but happy to hear feedback and/or better ideas for a streaming JSON API.
Since it would be boring to leave it at that, a bonus sneak peak for streaming via closure iterator (that could read from a file or database), once the above is settled:
type Item = tuple[id: int, name: string]
proc makeItems[Flavor](items: int): JsonArrayIterator[Item, Flavor] =
iterator (writer: var JsonWriter[Flavor]): Item =
for i in 0 ..< items:
yield (i, "item" & $i)
writer.writeValue((status: "ok", data: makeItems[writer.Flavor](2)))