Added structured error reporting to Reader.

This allows applications for interactively viewing or editing JSON to do
a better job of highlighting errors. Also added offset accessors to
Value, offering the same sort of functionality even for non-errors.

Thanks to Zach Clifford (zacharyc@google.com) for the patch.
This commit is contained in:
Aaron Jacobs
2014-04-23 23:41:12 +00:00
parent 642befc836
commit 68db655347
5 changed files with 269 additions and 3 deletions

View File

@@ -1474,6 +1474,26 @@ JSONTEST_FIXTURE( ValueTest, checkInteger )
}
JSONTEST_FIXTURE( ValueTest, offsetAccessors )
{
Json::Value x;
JSONTEST_ASSERT( x.getOffsetStart() == 0 );
JSONTEST_ASSERT( x.getOffsetLimit() == 0 );
x.setOffsetStart(10);
x.setOffsetLimit(20);
JSONTEST_ASSERT( x.getOffsetStart() == 10 );
JSONTEST_ASSERT( x.getOffsetLimit() == 20 );
Json::Value y(x);
JSONTEST_ASSERT( y.getOffsetStart() == 10 );
JSONTEST_ASSERT( y.getOffsetLimit() == 20 );
Json::Value z;
z.swap(y);
JSONTEST_ASSERT( z.getOffsetStart() == 10 );
JSONTEST_ASSERT( z.getOffsetLimit() == 20 );
JSONTEST_ASSERT( y.getOffsetStart() == 0 );
JSONTEST_ASSERT( y.getOffsetLimit() == 0 );
}
struct WriterTest : JsonTest::TestCase
{
};
@@ -1490,6 +1510,115 @@ JSONTEST_FIXTURE( WriterTest, dropNullPlaceholders )
}
struct ReaderTest : JsonTest::TestCase
{
};
JSONTEST_FIXTURE( ReaderTest, parseWithNoErrors )
{
Json::Reader reader;
Json::Value root;
bool ok = reader.parse(
"{ \"property\" : \"value\" }",
root);
JSONTEST_ASSERT( ok );
JSONTEST_ASSERT( reader.getFormattedErrorMessages().size() == 0 );
JSONTEST_ASSERT( reader.getStructuredErrors().size() == 0 );
}
JSONTEST_FIXTURE( ReaderTest, parseWithNoErrorsTestingOffsets )
{
Json::Reader reader;
Json::Value root;
bool ok = reader.parse(
"{ \"property\" : [\"value\", \"value2\"], \"obj\" : { \"nested\" : 123, \"bool\" : true}, \"null\" : null, \"false\" : false }",
root);
JSONTEST_ASSERT( ok );
JSONTEST_ASSERT( reader.getFormattedErrorMessages().size() == 0 );
JSONTEST_ASSERT( reader.getStructuredErrors().size() == 0 );
JSONTEST_ASSERT( root["property"].getOffsetStart() == 15 );
JSONTEST_ASSERT( root["property"].getOffsetLimit() == 34 );
JSONTEST_ASSERT( root["property"][0].getOffsetStart() == 16 );
JSONTEST_ASSERT( root["property"][0].getOffsetLimit() == 23 );
JSONTEST_ASSERT( root["property"][1].getOffsetStart() == 25 );
JSONTEST_ASSERT( root["property"][1].getOffsetLimit() == 33 );
JSONTEST_ASSERT( root["obj"].getOffsetStart() == 44 );
JSONTEST_ASSERT( root["obj"].getOffsetLimit() == 76 );
JSONTEST_ASSERT( root["obj"]["nested"].getOffsetStart() == 57 );
JSONTEST_ASSERT( root["obj"]["nested"].getOffsetLimit() == 60 );
JSONTEST_ASSERT( root["obj"]["bool"].getOffsetStart() == 71 );
JSONTEST_ASSERT( root["obj"]["bool"].getOffsetLimit() == 75 );
JSONTEST_ASSERT( root["null"].getOffsetStart() == 87 );
JSONTEST_ASSERT( root["null"].getOffsetLimit() == 91 );
JSONTEST_ASSERT( root["false"].getOffsetStart() == 103 );
JSONTEST_ASSERT( root["false"].getOffsetLimit() == 108 );
JSONTEST_ASSERT( root.getOffsetStart() == 0 );
JSONTEST_ASSERT( root.getOffsetLimit() == 110 );
}
JSONTEST_FIXTURE( ReaderTest, parseWithOneError )
{
Json::Reader reader;
Json::Value root;
bool ok = reader.parse(
"{ \"property\" :: \"value\" }",
root);
JSONTEST_ASSERT( !ok );
JSONTEST_ASSERT( reader.getFormattedErrorMessages() ==
"* Line 1, Column 15\n Syntax error: value, object or array expected.\n" );
std::vector<Json::Reader::StructuredError> errors =
reader.getStructuredErrors();
JSONTEST_ASSERT( errors.size() == 1 );
JSONTEST_ASSERT( errors.at(0).offset_start == 14 );
JSONTEST_ASSERT( errors.at(0).offset_limit == 15 );
JSONTEST_ASSERT( errors.at(0).message ==
"Syntax error: value, object or array expected." );
}
JSONTEST_FIXTURE( ReaderTest, parseChineseWithOneError )
{
Json::Reader reader;
Json::Value root;
bool ok = reader.parse(
"{ \"pr佐藤erty\" :: \"value\" }",
root);
JSONTEST_ASSERT( !ok );
JSONTEST_ASSERT( reader.getFormattedErrorMessages() ==
"* Line 1, Column 19\n Syntax error: value, object or array expected.\n" );
std::vector<Json::Reader::StructuredError> errors =
reader.getStructuredErrors();
JSONTEST_ASSERT( errors.size() == 1 );
JSONTEST_ASSERT( errors.at(0).offset_start == 18 );
JSONTEST_ASSERT( errors.at(0).offset_limit == 19 );
JSONTEST_ASSERT( errors.at(0).message ==
"Syntax error: value, object or array expected." );
}
JSONTEST_FIXTURE( ReaderTest, parseWithDetailError )
{
Json::Reader reader;
Json::Value root;
bool ok = reader.parse(
"{ \"property\" : \"v\\alue\" }",
root);
JSONTEST_ASSERT( !ok );
JSONTEST_ASSERT( reader.getFormattedErrorMessages() ==
"* Line 1, Column 16\n Bad escape sequence in string\nSee Line 1, Column 20 for detail.\n" );
std::vector<Json::Reader::StructuredError> errors =
reader.getStructuredErrors();
JSONTEST_ASSERT( errors.size() == 1 );
JSONTEST_ASSERT( errors.at(0).offset_start == 15 );
JSONTEST_ASSERT( errors.at(0).offset_limit == 23 );
JSONTEST_ASSERT( errors.at(0).message ==
"Bad escape sequence in string" );
}
int main( int argc, const char *argv[] )
{
JsonTest::Runner runner;
@@ -1512,6 +1641,14 @@ int main( int argc, const char *argv[] )
JSONTEST_REGISTER_FIXTURE( runner, ValueTest, compareObject );
JSONTEST_REGISTER_FIXTURE( runner, ValueTest, compareType );
JSONTEST_REGISTER_FIXTURE( runner, ValueTest, checkInteger );
JSONTEST_REGISTER_FIXTURE( runner, ValueTest, offsetAccessors );
JSONTEST_REGISTER_FIXTURE( runner, ReaderTest, parseWithNoErrors );
JSONTEST_REGISTER_FIXTURE( runner, ReaderTest, parseWithNoErrorsTestingOffsets );
JSONTEST_REGISTER_FIXTURE( runner, ReaderTest, parseWithOneError );
JSONTEST_REGISTER_FIXTURE( runner, ReaderTest, parseChineseWithOneError );
JSONTEST_REGISTER_FIXTURE( runner, ReaderTest, parseWithDetailError );
JSONTEST_REGISTER_FIXTURE( runner, WriterTest, dropNullPlaceholders );
return runner.runCommandLine( argc, argv );
}