cJSON icon indicating copy to clipboard operation
cJSON copied to clipboard

Print to stream

Open FSMaxB opened this issue 7 years ago • 6 comments

As suggested by @iMobs in #89.

It is not guaranteed, that cJSON will ever support streaming, but if it will, here's some ideas on how it could be done.

The print functions have been switched to only supporting buffered printing recently. Streaming could be done by allocating a buffer every time the ensure function is called and flushing that buffer to the stream on the next call (or when it exceeds a certain size).

An important thing to keep in mind: This buffer can not be allocated on the stack, because it needs to be able to take any length.

The streaming functions could be passed through with cJSON_Hooks or similar.

In that model, cJSON would also be the caller and the program that uses cJSON for streaming would be the callee.

FSMaxB avatar Mar 19 '17 10:03 FSMaxB

Wrappers that stream to a filedescriptor could be included in the library if this is implemented.

FSMaxB avatar May 02 '17 12:05 FSMaxB

I also need a feature like this and I'm willing to work on it. I agree that pull request #161 is not the way to go, because it is bound too tightly to that particular way of streaming. I would propose the following approach.

  • The streaming API goes into a separate file cJSON_Streaming.{c,h} so it is easy to leave out. Note that it doesn't belong in cJSON_Utils, because those are utilities for manipulating JSON, not for parsing/dumping.
  • It is based on callbacks to implement the read/write functionality, so it can be used for standard C I/O, POSIX fd I/O, async I/O, or any other streaming API.
  • We provide a standard C I/O-based implementation as an example, but it's not included in the library.

Note that by splitting it into a separate file, the streaming functionality will not be able to use the ensure() function. I'm not sure how to elegantly work around that. However, in my view, at least in the initial implementation, we should make no effort to flush the output as early as possible. Just construct the entire output string in a buffer.

For me, the main reason to have a streaming interface is not to have more efficient printing, but rather to have safe parsing. In streaming context, you have to repeatedly read() into a buffer until you have a complete object, then generate the cJSON object, then shift the remaining bytes of the buffer. That is a bit tricky to get correct, so certainly worthwhile to have inside cJSON. Getting it efficient is a second step.

arnout avatar Aug 28 '17 11:08 arnout

I don't want cJSON to have a streaming interface that doesn't actually do any streaming. I'm sure there are libraries out there that implement a dynamic buffer that you can continuously add data to, so use that if you need it!

A streaming interface should be contained in the main cJSON file.

Also note that the approach that I described in the comment above using the ensure function is about printing, not parsing. Implementing parsing might be a lot harder and I'm not sure if there will be a satisfactory solution.

FSMaxB avatar Aug 28 '17 15:08 FSMaxB

All right, then I'll just code my solution externally from cJSON.

arnout avatar Aug 30 '17 06:08 arnout

Will there be any update on this issue ? The cJSON library is often used in embedded hardware where printing using streaming interface is pretty handy.

The use case would be to stream the printing directly to serial interface or other. The might be blocking and non-blocking variant for some advanced HW interfaces.

optical-o avatar Aug 11 '22 08:08 optical-o

If you would rather users implement their own stream system, would it be possible to write an example that shows how this could be accomplished? For example I don't see a way to have cJSON print a chunk of the output string. I see printBuffered() but it's not clear how to use it ... would you call this in a loop, and expect a new chunk with each call? If so, how would you know when the string is done? Any advice super welcome, Thank you!

marchingband avatar Nov 06 '22 15:11 marchingband