Merge branch 'master' (1.4.1) into v0.8.z (0.8.1)

This commit is contained in:
Christopher Dunn 2015-02-13 10:26:07 -06:00
commit 721de4b9fd
7 changed files with 176 additions and 43 deletions

View File

@ -7,17 +7,20 @@ pairs.
[json-org]: http://json.org/
JsonCpp is a C++ library that allows manipulating JSON values, including
[JsonCpp][] is a C++ library that allows manipulating JSON values, including
serialization and deserialization to and from strings. It can also preserve
existing comment in unserialization/serialization steps, making it a convenient
format to store user input files.
[JsonCpp]: http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html
## A note on backward-compatibility
Very soon, we are switching to C++11 only. For older compilers, try the `pre-C++11` branch.
* `1.y.z` is built with C++11.
* `0.8.z` can be used with older compilers.
* Major versions maintain binary-compatibility.
Using JsonCpp in your project
-----------------------------
The recommended approach to integrating JsonCpp in your project is to build
the amalgamated source (a single `.cpp` file) with your own build system. This
ensures consistency of compilation flags and ABI compatibility. See the section
@ -28,13 +31,11 @@ should be included as follow:
#include <json/json.h>
If JsonCpp was build as a dynamic library on Windows, then your project needs to
If JsonCpp was built as a dynamic library on Windows, then your project needs to
define the macro `JSON_DLL`.
Building and testing with new CMake
-----------------------------------
Building and testing with CMake
-------------------------------
[CMake][] is a C++ Makefiles/Solution generator. It is usually available on most
Linux system as package. On Ubuntu:
@ -75,10 +76,8 @@ the `-G` option).
By default CMake hides compilation commands. This can be modified by specifying
`-DCMAKE_VERBOSE_MAKEFILE=true` when generating makefiles.
Building and testing with SCons
-------------------------------
**Note:** The SCons-based build system is deprecated. Please use CMake; see the
section above.
@ -107,14 +106,7 @@ If you are building with Microsoft Visual Studio 2008, you need to set up the
environment by running `vcvars32.bat` (e.g. MSVC 2008 command prompt) before
running SCons.
Running the tests manually
--------------------------
Note that test can be run using SCons using the `check` target:
scons platform=$PLATFORM check
# Running the tests manually
You need to run tests manually only if you are troubleshooting an issue.
In the instructions below, replace `path/to/jsontest` with the path of the
@ -137,20 +129,21 @@ In the instructions below, replace `path/to/jsontest` with the path of the
# You can run the tests using valgrind:
python rununittests.py --valgrind path/to/test_lib_json
## Running the tests using scons
Note that tests can be run using SCons using the `check` target:
scons platform=$PLATFORM check
Building the documentation
--------------------------
Run the Python script `doxybuild.py` from the top directory:
python doxybuild.py --doxygen=$(which doxygen) --open --with-dot
See `doxybuild.py --help` for options.
Generating amalgamated source and header
----------------------------------------
JsonCpp is provided with a script to generate a single header and a single
source file to ease inclusion into an existing project. The amalgamated source
can be generated at any time by running the following command from the
@ -172,10 +165,8 @@ The amalgamated sources are generated by concatenating JsonCpp source in the
correct order and defining the macro `JSON_IS_AMALGAMATION` to prevent inclusion
of other headers.
Adding a reader/writer test
---------------------------
To add a test, you need to create two files in test/data:
* a `TESTNAME.json` file, that contains the input document in JSON format.
@ -195,10 +186,8 @@ The `TESTNAME.expected` file format is as follows:
See the examples `test_complex_01.json` and `test_complex_01.expected` to better
understand element paths.
Understanding reader/writer test output
---------------------------------------
When a test is run, output files are generated beside the input test files.
Below is a short description of the content of each file:
@ -215,10 +204,7 @@ Below is a short description of the content of each file:
* `test_complex_01.process-output`: `jsontest` output, typically useful for
understanding parsing errors.
License
-------
See the `LICENSE` file for details. In summary, JsonCpp is licensed under the
MIT license, or public domain if desired and recognized in your jurisdiction.

View File

@ -56,20 +56,24 @@ std::cin >> root;
// You can also read into a particular sub-value.
std::cin >> root["subtree"];
// Get the value of the member of root named 'encoding', return 'UTF-8' if there is no
// such member.
// Get the value of the member of root named 'encoding',
// and return 'UTF-8' if there is no such member.
std::string encoding = root.get("encoding", "UTF-8" ).asString();
// Get the value of the member of root named 'encoding'; return a 'null' value if
// Get the value of the member of root named 'plug-ins'; return a 'null' value if
// there is no such member.
const Json::Value plugins = root["plug-ins"];
for ( int index = 0; index < plugins.size(); ++index ) // Iterates over the sequence elements.
// Iterate over the sequence elements.
for ( int index = 0; index < plugins.size(); ++index )
loadPlugIn( plugins[index].asString() );
// Try other datatypes. Some are auto-convertible to others.
foo::setIndentLength( root["indent"].get("length", 3).asInt() );
foo::setIndentUseSpace( root["indent"].get("use_space", true).asBool() );
// Since Json::Value has implicit constructor for all value types, it is not
// necessary to explicitly construct the Json::Value object:
// Since Json::Value has an implicit constructor for all value types, it is not
// necessary to explicitly construct the Json::Value object.
root["encoding"] = foo::getCurrentEncoding();
root["indent"]["length"] = foo::getCurrentIndentLength();
root["indent"]["use_space"] = foo::getCurrentIndentUseSpace();
@ -152,6 +156,7 @@ Basically JsonCpp is licensed under MIT license, or public domain if desired
and recognized in your jurisdiction.
\author Baptiste Lepilleur <blep@users.sourceforge.net> (originator)
\author Christopher Dunn <cdunn2001@gmail.com> (primary maintainer)
\version \include version
We make strong guarantees about binary-compatibility, consistent with
<a href="http://apr.apache.org/versioning.html">the Apache versioning scheme</a>.

View File

@ -254,21 +254,26 @@ public:
/** Configuration of this builder.
These are case-sensitive.
Available settings (case-sensitive):
- "collectComments": false or true
- `"collectComments": false or true`
- true to collect comment and allow writing them
back during serialization, false to discard comments.
This parameter is ignored if allowComments is false.
- "allowComments": false or true
- `"allowComments": false or true`
- true if comments are allowed.
- "strictRoot": false or true
- `"strictRoot": false or true`
- true if root must be either an array or an object value
- "allowDroppedNullPlaceholders": false or true
- `"allowDroppedNullPlaceholders": false or true`
- true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
- "allowNumericKeys": false or true
- `"allowNumericKeys": false or true`
- true if numeric object keys are allowed.
- "stackLimit": integer
- `"stackLimit": integer`
- Exceeding stackLimit (recursive depth of `readValue()`) will
cause an exception.
- This is a security issue (seg-faults caused by deeply nested JSON),
so the default is low.
- `"failIfExtra": false or true`
- If true, `parse()` returns false when extra non-whitespace trails
the JSON value in the input string.
You can examine 'settings_` yourself
to see the defaults. You can also write and read them just like any

View File

@ -4,10 +4,10 @@
#ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED
# define JSONCPP_VERSION_STRING "0.8.0"
# define JSONCPP_VERSION_STRING "0.8.1"
# define JSONCPP_VERSION_MAJOR 0
# define JSONCPP_VERSION_MINOR 8
# define JSONCPP_VERSION_PATCH 0
# define JSONCPP_VERSION_PATCH 1
# define JSONCPP_VERSION_QUALIFIER
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))

View File

@ -826,6 +826,7 @@ public:
bool strictRoot_;
bool allowDroppedNullPlaceholders_;
bool allowNumericKeys_;
bool failIfExtra_;
int stackLimit_;
}; // OurFeatures
@ -991,6 +992,12 @@ bool OurReader::parse(const char* beginDoc,
bool successful = readValue();
Token token;
skipCommentTokens(token);
if (features_.failIfExtra_) {
if (token.type_ != tokenError && token.type_ != tokenEndOfStream) {
addError("Extra non-whitespace after JSON value.", token);
return false;
}
}
if (collectComments_ && !commentsBefore_.empty())
root.setComment(commentsBefore_, commentAfter);
if (features_.strictRoot_) {
@ -1704,6 +1711,7 @@ CharReader* CharReaderBuilder::newCharReader() const
features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
features.stackLimit_ = settings_["stackLimit"].asInt();
features.failIfExtra_ = settings_["failIfExtra"].asBool();
return new OurCharReader(collectComments, features);
}
static void getValidReaderKeys(std::set<std::string>* valid_keys)
@ -1715,6 +1723,7 @@ static void getValidReaderKeys(std::set<std::string>* valid_keys)
valid_keys->insert("allowDroppedNullPlaceholders");
valid_keys->insert("allowNumericKeys");
valid_keys->insert("stackLimit");
valid_keys->insert("failIfExtra");
}
bool CharReaderBuilder::validate(Json::Value* invalid) const
{
@ -1742,6 +1751,7 @@ void CharReaderBuilder::strictMode(Json::Value* settings)
(*settings)["strictRoot"] = true;
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
(*settings)["failIfExtra"] = true;
//! [CharReaderBuilderStrictMode]
}
// static
@ -1754,6 +1764,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings)
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
(*settings)["stackLimit"] = 1000;
(*settings)["failIfExtra"] = false;
//! [CharReaderBuilderDefaults]
}

View File

@ -1671,6 +1671,126 @@ JSONTEST_FIXTURE(CharReaderTest, parseWithStackLimit) {
}
}
struct CharReaderFailIfExtraTest : JsonTest::TestCase {};
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue164) {
// This is interpretted as a string value followed by a colon.
Json::CharReaderBuilder b;
Json::Value root;
char const doc[] =
" \"property\" : \"value\" }";
{
b.settings_["failIfExtra"] = false;
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT(errs == "");
JSONTEST_ASSERT_EQUAL("property", root);
delete reader;
}
{
b.settings_["failIfExtra"] = true;
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(!ok);
JSONTEST_ASSERT_STRING_EQUAL(errs,
"* Line 1, Column 13\n"
" Extra non-whitespace after JSON value.\n");
JSONTEST_ASSERT_EQUAL("property", root);
delete reader;
}
{
b.settings_["failIfExtra"] = false;
b.strictMode(&b.settings_);
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(!ok);
JSONTEST_ASSERT_STRING_EQUAL(errs,
"* Line 1, Column 13\n"
" Extra non-whitespace after JSON value.\n");
JSONTEST_ASSERT_EQUAL("property", root);
delete reader;
}
}
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue107) {
// This is interpretted as an int value followed by a colon.
Json::CharReaderBuilder b;
Json::Value root;
char const doc[] =
"1:2:3";
b.settings_["failIfExtra"] = true;
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(!ok);
JSONTEST_ASSERT_STRING_EQUAL(
"* Line 1, Column 2\n"
" Extra non-whitespace after JSON value.\n",
errs);
JSONTEST_ASSERT_EQUAL(1, root.asInt());
delete reader;
}
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterObject) {
Json::CharReaderBuilder b;
Json::Value root;
{
char const doc[] =
"{ \"property\" : \"value\" } //trailing\n//comment\n";
b.settings_["failIfExtra"] = true;
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL("value", root["property"]);
delete reader;
}
}
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterArray) {
Json::CharReaderBuilder b;
Json::Value root;
char const doc[] =
"[ \"property\" , \"value\" ] //trailing\n//comment\n";
b.settings_["failIfExtra"] = true;
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL("value", root[1u]);
delete reader;
}
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterBool) {
Json::CharReaderBuilder b;
Json::Value root;
char const doc[] =
" true /*trailing\ncomment*/";
b.settings_["failIfExtra"] = true;
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(true, root.asBool());
delete reader;
}
int main(int argc, const char* argv[]) {
JsonTest::Runner runner;
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr);
@ -1708,6 +1828,12 @@ int main(int argc, const char* argv[]) {
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithDetailError);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithStackLimit);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue164);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue107);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, commentAfterObject);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, commentAfterArray);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, commentAfterBool);
JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders);
return runner.runCommandLine(argc, argv);

View File

@ -1 +1 @@
0.8.0
0.8.1