JSON Voorhees
Killer JSON for C++
Loading...
Searching...
No Matches
encode.hpp
Go to the documentation of this file.
1/** \file jsonv/encode.hpp
2 * Classes and functions for encoding JSON values to various representations.
3 *
4 * Copyright (c) 2014 by Travis Gockel. All rights reserved.
5 *
6 * This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
7 * as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
8 * version.
9 *
10 * \author Travis Gockel (travis@gockelhut.com)
11**/
12#pragma once
13
14#include <jsonv/config.hpp>
15#include <jsonv/forward.hpp>
16#include <string_view>
17
18#include <cstdint>
19#include <iosfwd>
20#include <memory>
21
22namespace jsonv
23{
24
25/** An encoder is responsible for writing values to some form of output.
26 *
27 * It is a sink for the tokens of a JSON document: a \c writer drives the \c write_ hooks below one token at a time,
28 * writing the delimiters between elements and members itself. A whole \c value, handed to \c encode or to
29 * \c writer::write, arrives through \c write_tree, which by default walks it through those same hooks. An
30 * implementation turns each token into text, as \c ostream_encoder does, or into anything else.
31 *
32 * \see writer
33**/
35{
36public:
37 virtual ~encoder() noexcept;
38
39 /** Encode some source value into this encoder, through \c write_tree. To write a document token by token instead
40 * of from a finished \c value, construct a \c writer over this encoder; its \c writer::write does the same.
41 **/
42 void encode(const jsonv::value& source);
43
44protected:
45 /** Write the null value.
46 *
47 * \code
48 * null
49 * \endcode
50 **/
51 virtual void write_null() = 0;
52
53 /** Write the opening of an object value.
54 *
55 * \code
56 * {
57 * \endcode
58 **/
59 virtual void write_object_begin() = 0;
60
61 /** Write the closing of an object value.
62 *
63 * \code
64 * }
65 * \endcode
66 **/
67 virtual void write_object_end() = 0;
68
69 /** Write the key for an object, including the separator.
70 *
71 * \code
72 * "key":
73 * \endcode
74 **/
75 virtual void write_object_key(std::string_view key) = 0;
76
77 /** Write the delimiter between two entries in an object.
78 *
79 * \code
80 * ,
81 * \endcode
82 **/
83 virtual void write_object_delimiter() = 0;
84
85 /** Write the opening of an array value.
86 *
87 * \code
88 * [
89 * \endcode
90 **/
91 virtual void write_array_begin() = 0;
92
93 /** Write the closing of an array value.
94 *
95 * \code
96 * ]
97 * \endcode
98 **/
99 virtual void write_array_end() = 0;
100
101 /** Write the delimiter between two entries in an array.
102 *
103 * \code
104 * ,
105 * \endcode
106 **/
107 virtual void write_array_delimiter() = 0;
108
109 /** Write a string value.
110 *
111 * \param value is the string to write. It will \e hopefully be encoded as valid UTF-8. It is the implementation's
112 * choice of how to deal with malformed string values. Two common options are to replace malformed
113 * sequences with ?s or to simply output these encodings and let the receiver deal with them.
114 *
115 * \code
116 * "value"
117 * \endcode
118 **/
119 virtual void write_string(std::string_view value) = 0;
120
121 /** Write an integer value.
122 *
123 * \code
124 * 902
125 * \endcode
126 **/
127 virtual void write_integer(std::int64_t value) = 0;
128
129 /** Write a decimal value.
130 *
131 * \param value is the decimal to write. Keep in mind that standard JSON does not support special IEEE 754 values
132 * such as NaN and infinity. It is the implementation's choice of how to deal with such values. Two
133 * common options are to output \c null or to encode a string description of the special value.
134 *
135 * \code
136 * 4.9
137 * \endcode
138 **/
139 virtual void write_decimal(double value) = 0;
140
141 /** Write a boolean value.
142 *
143 * \code
144 * true
145 * \endcode
146 **/
147 virtual void write_boolean(bool value) = 0;
148
149 /** Write \a source and everything under it as one value, taking it over. A \c writer calls this for a \c value it
150 * is handed as an rvalue. The default writes it as an lvalue is written, through the overload below; a sink
151 * which builds a tree, as \c value_encoder does, overrides it to take the value as it is rather than copy it.
152 **/
153 virtual void write_tree(jsonv::value&& source);
154
155 /** Write \a source and everything under it as one value. \c encode calls this, and so does a \c writer for a
156 * \c value it is handed as an lvalue. The default walks the tree through the hooks above, with an object's
157 * members in the order the object keeps them and the delimiters written here, which is what a sink producing
158 * text wants: a \c value is well-formed by construction, so nothing checks the grammar inside one. A sink which
159 * builds a tree, as \c value_encoder does, overrides it to copy the value whole rather than rebuild it node by
160 * node.
161 **/
162 virtual void write_tree(const jsonv::value& source);
163
164private:
165 /** The walk behind the default \c write_tree. It recurses into itself rather than into the hook, which is for a
166 * whole value handed in and not for each subtree of one.
167 **/
168 void walk_tree(const jsonv::value& source);
169
170 /// The hooks above are driven by a \c writer, which is what keeps the sequence of calls spelling a valid document.
171 friend class writer;
172};
173
174/** An encoder that outputs to an \c std::ostream. This implementation is used for \c operator<< on a \c value.
175 *
176 * Text goes into the stream unformatted, so the stream's format flags, width, fill and locale have no say in the JSON
177 * written, and are left as the caller set them. A width set before <tt>os << some_value</tt> applies to whatever is
178 * inserted after it, not to the document.
179**/
181 public encoder
182{
183public:
184 /** Create an instance which places text into \a output. **/
185 explicit ostream_encoder(std::ostream& output);
186
187 virtual ~ostream_encoder() noexcept;
188
189 /** If set to true (the default), then all non-ASCII characters in strings will be replaced with their numeric
190 * encodings. Since JSON allows for encoded text to be contained in a document, this is inefficient if you have
191 * many non-ASCII characters. If you know that your decoding side can properly handle UTF-8 encoding, then you
192 * should turn this off, and well-formed UTF-8 will be written out as it is. An \c ostream_pretty_encoder follows
193 * this setting too.
194 *
195 * \note
196 * This functionality cannot be used to passthrough malformed UTF-8 encoded strings or control characters. If a
197 * given string is invalid UTF-8, it will still get replaced with a numeric encoding, and so will any character
198 * JSON requires to be escaped.
199 **/
200 void ensure_ascii(bool value);
201
202protected:
203 virtual void write_null() override;
204
205 virtual void write_object_begin() override;
206
207 virtual void write_object_end() override;
208
209 virtual void write_object_key(std::string_view key) override;
210
211 virtual void write_object_delimiter() override;
212
213 virtual void write_array_begin() override;
214
215 virtual void write_array_end() override;
216
217 virtual void write_array_delimiter() override;
218
219 virtual void write_string(std::string_view value) override;
220
221 virtual void write_integer(std::int64_t value) override;
222
223 /** When a special value is given, this will output \c null. **/
224 virtual void write_decimal(double value) override;
225
226 virtual void write_boolean(bool value) override;
227
228protected:
229 /** The stream text goes into. Write to it unformatted, with \c put and \c write, as this class does. A formatted
230 * insertion would let the stream's state into the JSON, and would use up a width the caller left pending.
231 **/
232 std::ostream& output();
233
234private:
235 std::ostream& _output;
236 bool _ensure_ascii;
237};
238
239/** Like \c ostream_encoder, but pretty prints output to an \c std::ostream. For example, to pretty-print JSON to
240 * \c std::cout:
241 *
242 * \code
243 * jsonv::ostream_pretty_encoder encoder(std::cout);
244 * encoder.encode(some_value);
245 * encoder.encode(another_value);
246 * \endcode
247**/
249 public ostream_encoder
250{
251public:
252 /** Create an instance which places text into \a output. **/
253 explicit ostream_pretty_encoder(std::ostream& output, std::size_t indent_size = 2);
254
255 virtual ~ostream_pretty_encoder() noexcept;
256
257protected:
258 virtual void write_null() override;
259
260 virtual void write_object_begin() override;
261
262 virtual void write_object_end() override;
263
264 virtual void write_object_key(std::string_view key) override;
265
266 virtual void write_object_delimiter() override;
267
268 virtual void write_array_begin() override;
269
270 virtual void write_array_end() override;
271
272 virtual void write_array_delimiter() override;
273
274 virtual void write_string(std::string_view value) override;
275
276 virtual void write_integer(std::int64_t value) override;
277
278 virtual void write_decimal(double value) override;
279
280 virtual void write_boolean(bool value) override;
281
282private:
283 void write_prefix();
284
285 void write_eol();
286
287private:
288 std::size_t _indent;
289 std::size_t _indent_size;
290 bool _defer_indent;
291};
292
293/** An encoder which builds a \c value from the tokens it is given: the sink for a document which is produced token by
294 * token through a \c writer but is wanted as a tree. It is the mirror of \c reader::from_value, which hands a tree
295 * out as tokens.
296 *
297 * \code
298 * jsonv::value_encoder sink;
299 * jsonv::writer to(sink);
300 * to.object_begin()
301 * .key("a").integer(1)
302 * .key("b").array_begin().string("x").string("y").array_end()
303 * .object_end();
304 * jsonv::value built = std::move(sink).take(); // {"a":1,"b":["x","y"]}
305 * \endcode
306 *
307 * An object is built as a \c value keeps one, so a key which repeats within it keeps the value written last, as
308 * \c parse keeps it by default; a document built from tokens and the same document parsed from text select the same
309 * data. The encoder holds one document at a time: a second root value written before \c take replaces the first, as
310 * a repeated key does.
311 *
312 * \see writer
313 * \see reader::from_value
314**/
316 public encoder
317{
318public:
319 /** Create an instance holding nothing. **/
320 explicit value_encoder();
321
322 // Not copyable or movable. A writer keeps a pointer to its encoder, so an encoder which moved out from under it
323 // would be a bug rather than a feature, and nothing else needs one to move.
324 value_encoder(const value_encoder&) = delete;
325 value_encoder& operator=(const value_encoder&) = delete;
326 value_encoder(value_encoder&&) = delete;
327 value_encoder& operator=(value_encoder&&) = delete;
328
329 virtual ~value_encoder() noexcept override;
330
331 /** Hand out the document written so far. This instance is left holding nothing, as it was constructed, so another
332 * document may follow.
333 *
334 * \throws std::logic_error if an object or array is still open, or if nothing has been written at all. A JSON
335 * document is never empty, so a writer which has produced nothing has not produced
336 * \c null.
337 **/
339 value take() &&;
340
341protected:
342 virtual void write_null() override;
343
344 virtual void write_object_begin() override;
345
346 virtual void write_object_end() override;
347
348 /** Keep \a key for the member whose value comes next. **/
349 virtual void write_object_key(std::string_view key) override;
350
351 /** Does nothing: a tree has no punctuation. **/
352 virtual void write_object_delimiter() override;
353
354 virtual void write_array_begin() override;
355
356 virtual void write_array_end() override;
357
358 /** Does nothing: a tree has no punctuation. **/
359 virtual void write_array_delimiter() override;
360
361 /** The string is copied into the tree as it is, valid UTF-8 or not. **/
362 virtual void write_string(std::string_view value) override;
363
364 virtual void write_integer(std::int64_t value) override;
365
366 /** Kept as given: a \c value can hold a NaN or an infinity, so nothing is substituted for one. **/
367 virtual void write_decimal(double value) override;
368
369 virtual void write_boolean(bool value) override;
370
371 /** Takes \a source as it is. A tree handed over whole is placed where the next value goes without being rebuilt,
372 * which is what keeps a serializer on the \c value bridge linear in the depth of what it serializes.
373 **/
374 virtual void write_tree(jsonv::value&& source) override;
375
376 /** Copies \a source in whole. A tree written as an lvalue -- \c to_json of a \c value, or of anything holding
377 * one -- costs what copying it does rather than a rebuild through the hooks above, which inserts each member and
378 * grows each array one element at a time.
379 **/
380 virtual void write_tree(const jsonv::value& source) override;
381
382private:
383 class impl;
384
385private:
386 std::unique_ptr<impl> _impl;
387};
388
389}
An encoder is responsible for writing values to some form of output.
Definition encode.hpp:35
virtual void write_object_begin()=0
Write the opening of an object value.
virtual void write_tree(const jsonv::value &source)
Write source and everything under it as one value.
virtual void write_decimal(double value)=0
Write a decimal value.
virtual void write_array_begin()=0
Write the opening of an array value.
virtual void write_array_delimiter()=0
Write the delimiter between two entries in an array.
virtual void write_string(std::string_view value)=0
Write a string value.
virtual void write_object_end()=0
Write the closing of an object value.
void encode(const jsonv::value &source)
Encode some source value into this encoder, through write_tree.
virtual void write_object_key(std::string_view key)=0
Write the key for an object, including the separator.
virtual void write_integer(std::int64_t value)=0
Write an integer value.
virtual void write_tree(jsonv::value &&source)
Write source and everything under it as one value, taking it over.
virtual void write_null()=0
Write the null value.
virtual void write_object_delimiter()=0
Write the delimiter between two entries in an object.
virtual void write_boolean(bool value)=0
Write a boolean value.
virtual void write_array_end()=0
Write the closing of an array value.
An encoder that outputs to an std::ostream.
Definition encode.hpp:182
ostream_encoder(std::ostream &output)
Create an instance which places text into output.
Like ostream_encoder, but pretty prints output to an std::ostream.
Definition encode.hpp:250
ostream_pretty_encoder(std::ostream &output, std::size_t indent_size=2)
Create an instance which places text into output.
An encoder which builds a value from the tokens it is given: the sink for a document which is produce...
Definition encode.hpp:317
value_encoder()
Create an instance holding nothing.
Represents a single JSON value, which can be any one of a potential kind, each behaving slightly diff...
Definition value.hpp:165
A writer instance writes a JSON ast_node sequence to some form of sink: an encoder,...
Definition writer.hpp:68
Copyright (c) 2014-2020 by Travis Gockel.
Copyright (c) 2012-2020 by Travis Gockel.
#define JSONV_NODISCARD
Warn if the caller discards the result of this function.
Definition config.hpp:143
#define JSONV_PUBLIC
This function or class is part of the public API for JSON Voorhees.
Definition config.hpp:124
STL namespace.