Open veqryn opened 3 months ago
I don't see a way to clone the Encoder.
If the Encoder
backs a bytes.Buffer
, then clone might have obvious semantics (as we can clone the underlying bytes.Buffer
as well). But if it backs an arbitrary io.Writer
, what does that mean?
Perhaps instead of being able to clone the Encoder
, how about being able to create a new Encoder
if given a []byte
or bytes.Buffer
?
Or perhaps there is a better way to accomplish this?
A great example of the problem:
stdlib log/slog
's JSONHandler
, in particular how it piecemeal adds log attributes to a buffer to manually construct the JSON log line
Here is the library I have written, based off of log/slog
JSONHandler, but converted to use your JSON v2 library. It also faces the same issue:
https://github.com/veqryn/slog-json
I would like to piecemeal construct a single json object or array. Ideally, I would like to be able to clone the Encoder at any point, so that I can have multiple versions of the partially finished json. The main use case right now, is a slog.Handler that will be able to partially write the json as attributes are added, so that it doesn't need to fully marshal all of the attributes every time (similar to the built-in slog handlers, but using this json v2 library so I can take advantage of the new encoder options like SpaceAfterComma).
Example attempt:
Right now, I am encountering a few problems:
The values are being parsed twice. In the example above, I am using the regular
json.Marshal(...)
to turn anany
into ajsontext.Value
, then writing that value to the encoder. When writing to the encoder, it automatically re-parses the []byte value to confirm it is valid json. This is unneeded and a performance penalty.I don't see a way to clone the Encoder. There isn't a method to create a new encoder with an existing buffer or any of the encoder's state set. If I choose to replace the encoder with a simple buffer, I would lose out on all the encoder's guarantees and the jsontext.Options available, or have to re-implement them myself.
Is there an existing better way to do this?
If not, could we discuss what api additions or changes would be needed to allow this use case?