Skip to content

Commit 04a607d

Browse files
committed
Merge pull request open-source-parsers#163 from cdunn2001/master
Reimplement the new Builders. Issue open-source-parsers#131.
2 parents 732abb8 + db75cdf commit 04a607d

File tree

6 files changed

+294
-141
lines changed

6 files changed

+294
-141
lines changed

doc/jsoncpp.dox

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,26 @@ preserved.
5353
Json::Value root; // 'root' will contain the root value after parsing.
5454
std::cin >> root;
5555

56+
// You can also read into a particular sub-value.
57+
std::cin >> root["subtree"];
58+
5659
// Get the value of the member of root named 'encoding', return 'UTF-8' if there is no
5760
// such member.
5861
std::string encoding = root.get("encoding", "UTF-8" ).asString();
59-
// Get the value of the member of root named 'encoding', return a 'null' value if
62+
// Get the value of the member of root named 'encoding'; return a 'null' value if
6063
// there is no such member.
6164
const Json::Value plugins = root["plug-ins"];
6265
for ( int index = 0; index < plugins.size(); ++index ) // Iterates over the sequence elements.
6366
loadPlugIn( plugins[index].asString() );
6467

65-
setIndentLength( root["indent"].get("length", 3).asInt() );
66-
setIndentUseSpace( root["indent"].get("use_space", true).asBool() );
68+
foo::setIndentLength( root["indent"].get("length", 3).asInt() );
69+
foo::setIndentUseSpace( root["indent"].get("use_space", true).asBool() );
6770

6871
// Since Json::Value has implicit constructor for all value types, it is not
6972
// necessary to explicitly construct the Json::Value object:
70-
root["encoding"] = getCurrentEncoding();
71-
root["indent"]["length"] = getCurrentIndentLength();
72-
root["indent"]["use_space"] = getCurrentIndentUseSpace();
73+
root["encoding"] = foo::getCurrentEncoding();
74+
root["indent"]["length"] = foo::getCurrentIndentLength();
75+
root["indent"]["use_space"] = foo::getCurrentIndentUseSpace();
7376

7477
// If you like the defaults, you can insert directly into a stream.
7578
std::cout << root;
@@ -80,27 +83,40 @@ std::cout << std::endl;
8083
\endcode
8184

8285
\section _advanced Advanced usage
83-
We are finalizing the new *Builder* API, which will be in versions
84-
`1.4.0` and `0.8.0` when released. Until then, you may continue to
85-
use the old API, include `Writer`, `Reader`, and `Feature`.
86-
\code
8786

88-
// EXPERIMENTAL
89-
// Or use `writeString()` for convenience, with a specialized builder.
90-
Json::StreamWriterBuilder wbuilder;
91-
builder.indentation_ = "\t";
92-
std::string document = Json::writeString(root, wbuilder);
87+
Configure *builders* to create *readers* and *writers*. For
88+
configuration, we use our own `Json::Value` (rather than
89+
standard setters/getters) so that we can add
90+
features without losing binary-compatibility.
9391

94-
// You can also read into a particular sub-value.
95-
std::cin >> root["subtree"];
92+
\code
93+
// For convenience, use `writeString()` with a specialized builder.
94+
Json::StreamWriterBuilder wbuilder;
95+
wbuilder.settings_["indentation"] = "\t"; // simple Json::Value
96+
std::string document = Json::writeString(wbuilder, root);
9697

97-
// EXPERIMENTAL
98-
// Here we use a specialized Builder, discard comments, and
99-
// record errors.
98+
// Here, using a specialized Builder, we discard comments and
99+
// record errors as we parse.
100100
Json::CharReaderBuilder rbuilder;
101-
rbuilder.collectComments_ = false;
101+
rbuilder.settings_["collectComments"] = false; // simple Json::Value
102102
std::string errs;
103-
Json::parseFromStream(rbuilder, std::cin, &root["subtree"], &errs);
103+
bool ok = Json::parseFromStream(rbuilder, std::cin, &root, &errs);
104+
\endcode
105+
106+
Yes, compile-time configuration-checking would be helpful,
107+
but `Json::Value` lets you
108+
write and read the builder configuration, which is better! In other words,
109+
you can configure your JSON parser using JSON.
110+
111+
CharReaders and StreamWriters are not thread-safe, but they are re-usable.
112+
\code
113+
Json::CharReaderBuilder rbuilder;
114+
cfg >> rbuilder.settings_;
115+
std::unique_ptr<Json::CharReader> const reader(rbuilder.newCharReader());
116+
reader->parse(start, stop, &value1, &errs);
117+
// ...
118+
reader->parse(start, stop, &value2, &errs);
119+
// etc.
104120
\endcode
105121

106122
\section _pbuild Build instructions
@@ -137,5 +153,7 @@ and recognized in your jurisdiction.
137153

138154
\author Baptiste Lepilleur <[email protected]> (originator)
139155
\version \include version
156+
We make strong guarantees about binary-compatibility, consistent with
157+
<a href="http://apr.apache.org/versioning.html">the Apache versioning scheme</a>.
140158
\sa version.h
141159
*/

include/json/reader.h

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,9 @@ class JSON_API CharReader {
270270

271271
class Factory {
272272
public:
273-
/// \brief Allocate a CharReader via operator new().
273+
/** \brief Allocate a CharReader via operator new().
274+
* \throw std::exception if something goes wrong (e.g. invalid settings)
275+
*/
274276
virtual CharReader* newCharReader() const = 0;
275277
}; // Factory
276278
}; // CharReader
@@ -283,29 +285,53 @@ class JSON_API CharReader {
283285
\code
284286
using namespace Json;
285287
CharReaderBuilder builder;
286-
builder.collectComments_ = false;
288+
builder.settings_["collectComments"] = false;
287289
Value value;
288290
std::string errs;
289291
bool ok = parseFromStream(builder, std::cin, &value, &errs);
290292
\endcode
291293
*/
292-
class CharReaderBuilder : public CharReader::Factory {
294+
class JSON_API CharReaderBuilder : public CharReader::Factory {
293295
public:
294-
/** default: true
295-
*
296-
* It is possible to "allow" comments but still not "collect" them.
297-
*/
298-
bool collectComments_;
299-
/** default: all()
300-
*
301-
* For historical reasons, Features is a separate structure.
302-
*/
303-
Features features_;
296+
// Note: We use a Json::Value so that we can add data-members to this class
297+
// without a major version bump.
298+
/** Configuration of this builder.
299+
These are case-sensitive.
300+
Available settings (case-sensitive):
301+
- "collectComments": false or true
302+
- "allowComments"
303+
- "strictRoot"
304+
- "allowDroppedNullPlaceholders"
305+
- "allowNumericKeys"
306+
307+
You can examine 'settings_` yourself
308+
to see the defaults. You can also write and read them just like any
309+
JSON Value.
310+
\sa setDefaults()
311+
*/
312+
Json::Value settings_;
304313

305314
CharReaderBuilder();
306315
virtual ~CharReaderBuilder();
307316

308317
virtual CharReader* newCharReader() const;
318+
319+
/** \return true if 'settings' are legal and consistent;
320+
* otherwise, indicate bad settings via 'invalid'.
321+
*/
322+
bool validate(Json::Value* invalid) const;
323+
/** Called by ctor, but you can use this to reset settings_.
324+
* \pre 'settings' != NULL (but Json::null is fine)
325+
* \remark Defaults:
326+
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
327+
*/
328+
static void setDefaults(Json::Value* settings);
329+
/** Same as old Features::strictMode().
330+
* \pre 'settings' != NULL (but Json::null is fine)
331+
* \remark Defaults:
332+
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
333+
*/
334+
static void strictMode(Json::Value* settings);
309335
};
310336

311337
/** Consume entire stream and use its begin/end.

include/json/writer.h

Lines changed: 57 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -31,85 +31,93 @@ class Value;
3131
using namespace Json;
3232
void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
3333
std::unique_ptr<StreamWriter> const writer(
34-
factory.newStreamWriter(&std::cout));
35-
writer->write(value);
34+
factory.newStreamWriter());
35+
writer->write(value, &std::cout);
3636
std::cout << std::endl; // add lf and flush
3737
}
3838
\endcode
3939
*/
4040
class JSON_API StreamWriter {
4141
protected:
42-
std::ostream& sout_; // not owned; will not delete
42+
std::ostream* sout_; // not owned; will not delete
4343
public:
44-
/// Scoped enums are not available until C++11.
45-
struct CommentStyle {
46-
/// Decide whether to write comments.
47-
enum Enum {
48-
None, ///< Drop all comments.
49-
Most, ///< Recover odd behavior of previous versions (not implemented yet).
50-
All ///< Keep all comments.
51-
};
52-
};
53-
54-
/// Keep a reference, but do not take ownership of `sout`.
55-
StreamWriter(std::ostream* sout);
44+
StreamWriter();
5645
virtual ~StreamWriter();
57-
/// Write Value into document as configured in sub-class.
58-
/// \return zero on success
59-
/// \throw std::exception possibly, depending on configuration
60-
virtual int write(Value const& root) = 0;
46+
/** Write Value into document as configured in sub-class.
47+
Do not take ownership of sout, but maintain a reference during function.
48+
\pre sout != NULL
49+
\return zero on success
50+
\throw std::exception possibly, depending on configuration
51+
*/
52+
virtual int write(Value const& root, std::ostream* sout) = 0;
6153

6254
/** \brief A simple abstract factory.
6355
*/
6456
class JSON_API Factory {
6557
public:
6658
virtual ~Factory();
67-
/// Do not take ownership of sout, but maintain a reference.
68-
virtual StreamWriter* newStreamWriter(std::ostream* sout) const = 0;
59+
/** \brief Allocate a CharReader via operator new().
60+
* \throw std::exception if something goes wrong (e.g. invalid settings)
61+
*/
62+
virtual StreamWriter* newStreamWriter() const = 0;
6963
}; // Factory
7064
}; // StreamWriter
7165

72-
/// \brief Write into stringstream, then return string, for convenience.
73-
std::string writeString(Value const& root, StreamWriter::Factory const& factory);
66+
/** \brief Write into stringstream, then return string, for convenience.
67+
* A StreamWriter will be created from the factory, used, and then deleted.
68+
*/
69+
std::string writeString(StreamWriter::Factory const& factory, Value const& root);
7470

7571

7672
/** \brief Build a StreamWriter implementation.
7773
78-
\deprecated This is experimental and will be altered before the next release.
79-
8074
Usage:
8175
\code
8276
using namespace Json;
8377
Value value = ...;
8478
StreamWriterBuilder builder;
85-
builder.cs_ = StreamWriter::CommentStyle::None;
86-
builder.indentation_ = " "; // or whatever you like
87-
writer->write(value);
79+
builder.settings_["commentStyle"] = "None";
80+
builder.settings_["indentation"] = " "; // or whatever you like
81+
std::unique_ptr<Json::StreamWriter> writer(
82+
builder.newStreamWriter());
83+
writer->write(value, &std::cout);
8884
std::cout << std::endl; // add lf and flush
8985
\endcode
9086
*/
9187
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
9288
public:
93-
// Note: We cannot add data-members to this class without a major version bump.
94-
// So these might as well be completely exposed.
95-
96-
/** \brief How to write comments.
97-
* Default: All
98-
*/
99-
StreamWriter::CommentStyle::Enum cs_;
100-
/** \brief Write in human-friendly style.
101-
102-
If "", then skip all indentation and newlines.
103-
In that case, you probably want CommentStyle::None also.
104-
Default: "\t"
105-
*/
106-
std::string indentation_;
89+
// Note: We use a Json::Value so that we can add data-members to this class
90+
// without a major version bump.
91+
/** Configuration of this builder.
92+
Available settings (case-sensitive):
93+
- "commentStyle": "None", "Some", or "All"
94+
- "indentation": "<anything>"
95+
96+
You can examine 'settings_` yourself
97+
to see the defaults. You can also write and read them just like any
98+
JSON Value.
99+
\sa setDefaults()
100+
*/
101+
Json::Value settings_;
107102

108103
StreamWriterBuilder();
109104
virtual ~StreamWriterBuilder();
110105

111-
/// Do not take ownership of sout, but maintain a reference.
112-
virtual StreamWriter* newStreamWriter(std::ostream* sout) const;
106+
/**
107+
* \throw std::exception if something goes wrong (e.g. invalid settings)
108+
*/
109+
virtual StreamWriter* newStreamWriter() const;
110+
111+
/** \return true if 'settings' are legal and consistent;
112+
* otherwise, indicate bad settings via 'invalid'.
113+
*/
114+
bool validate(Json::Value* invalid) const;
115+
/** Called by ctor, but you can use this to reset settings_.
116+
* \pre 'settings' != NULL (but Json::null is fine)
117+
* \remark Defaults:
118+
* \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
119+
*/
120+
static void setDefaults(Json::Value* settings);
113121
};
114122

115123
/** \brief Build a StreamWriter implementation.
@@ -120,10 +128,12 @@ class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
120128
* \code
121129
* OldCompressingStreamWriterBuilder b;
122130
* b.dropNullPlaceHolders_ = true; // etc.
123-
* StreamWriter* w = b.newStreamWriter(&std::cout);
124-
* w->write(value);
131+
* StreamWriter* w = b.newStreamWriter();
132+
* w->write(value, &std::cout);
125133
* delete w;
126134
* \endcode
135+
*
136+
* \deprecated Use StreamWriterBuilder
127137
*/
128138
class JSON_API OldCompressingStreamWriterBuilder : public StreamWriter::Factory
129139
{
@@ -155,7 +165,7 @@ class JSON_API OldCompressingStreamWriterBuilder : public StreamWriter::Factory
155165
, omitEndingLineFeed_(false)
156166
, enableYAMLCompatibility_(false)
157167
{}
158-
virtual StreamWriter* newStreamWriter(std::ostream*) const;
168+
virtual StreamWriter* newStreamWriter() const;
159169
};
160170

161171
/** \brief Abstract class for writers.

src/jsontestrunner/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ static std::string useBuiltStyledStreamWriter(
185185
Json::Value const& root)
186186
{
187187
Json::StreamWriterBuilder builder;
188-
return writeString(root, builder);
188+
return Json::writeString(builder, root);
189189
}
190190
static int rewriteValueTree(
191191
const std::string& rewritePath,

0 commit comments

Comments
 (0)