mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-13 18:45:10 +01:00
Stricter JSON standard conformance (#2153)
This commit is contained in:
parent
bc39165811
commit
af09a02a34
@ -57,13 +57,17 @@ struct Foundation_API UTF8
|
||||
/// Remove the UTF-8 Byte Order Mark sequence (0xEF, 0xBB, 0xBF)
|
||||
/// from the beginning of the string, if it's there.
|
||||
|
||||
static std::string escape(const std::string& s);
|
||||
static std::string escape(const std::string& s, bool strictJSON = false);
|
||||
/// Escapes a string. Special characters like tab, backslash, ... are
|
||||
/// escaped. Unicode characters are escaped to \uxxxx.
|
||||
/// If strictJSON is true, \a and \v will be escaped to \\u0007 and \\u000B
|
||||
/// instead of \\a and \\v for strict JSON conformance.
|
||||
|
||||
static std::string escape(const std::string::const_iterator& begin, const std::string::const_iterator& end);
|
||||
static std::string escape(const std::string::const_iterator& begin, const std::string::const_iterator& end, bool strictJSON = false);
|
||||
/// Escapes a string. Special characters like tab, backslash, ... are
|
||||
/// escaped. Unicode characters are escaped to \uxxxx.
|
||||
/// If strictJSON is true, \a and \v will be escaped to \\u0007 and \\u000B
|
||||
/// instead of \\a and \\v for strict JSON conformance.
|
||||
|
||||
static std::string unescape(const std::string& s);
|
||||
/// Creates an UTF8 string from a string that contains escaped characters.
|
||||
|
@ -42,7 +42,7 @@ void writeString(const std::string &value, T& obj, typename WriteFunc<T, S>::Typ
|
||||
if(wrap) (obj.*write)("\"", 1);
|
||||
if(escapeAllUnicode)
|
||||
{
|
||||
std::string str = Poco::UTF8::escape(value.begin(), value.end());
|
||||
std::string str = Poco::UTF8::escape(value.begin(), value.end(), true);
|
||||
(obj.*write)(str.c_str(), str.size());
|
||||
}
|
||||
else
|
||||
@ -52,7 +52,7 @@ void writeString(const std::string &value, T& obj, typename WriteFunc<T, S>::Typ
|
||||
// Forward slash isn't strictly required by JSON spec, but some parsers expect it
|
||||
if((*it >= 0 && *it <= 31) || (*it == '"') || (*it == '\\') || (*it == '/'))
|
||||
{
|
||||
std::string str = Poco::UTF8::escape(it, it + 1);
|
||||
std::string str = Poco::UTF8::escape(it, it + 1, true);
|
||||
(obj.*write)(str.c_str(), str.size());
|
||||
}else (obj.*write)(&(*it), 1);
|
||||
}
|
||||
|
@ -171,12 +171,12 @@ void UTF8::removeBOM(std::string& str)
|
||||
}
|
||||
}
|
||||
|
||||
std::string UTF8::escape(const std::string &s)
|
||||
std::string UTF8::escape(const std::string &s, bool strictJSON)
|
||||
{
|
||||
return escape(s.begin(), s.end());
|
||||
return escape(s.begin(), s.end(), strictJSON);
|
||||
}
|
||||
|
||||
std::string UTF8::escape(const std::string::const_iterator& begin, const std::string::const_iterator& end)
|
||||
std::string UTF8::escape(const std::string::const_iterator& begin, const std::string::const_iterator& end, bool strictJSON)
|
||||
{
|
||||
static Poco::UInt32 offsetsFromUTF8[6] = {
|
||||
0x00000000UL, 0x00003080UL, 0x000E2080UL,
|
||||
@ -206,8 +206,8 @@ std::string UTF8::escape(const std::string::const_iterator& begin, const std::st
|
||||
else if (ch == '\r') result += "\\r";
|
||||
else if (ch == '\b') result += "\\b";
|
||||
else if (ch == '\f') result += "\\f";
|
||||
else if (ch == '\v') result += "\\v";
|
||||
else if (ch == '\a') result += "\\a";
|
||||
else if (ch == '\v') result += (strictJSON ? "\\u000B" : "\\v");
|
||||
else if (ch == '\a') result += (strictJSON ? "\\u0007" : "\\a");
|
||||
else if (ch == '\\') result += "\\\\";
|
||||
else if (ch == '\"') result += "\\\"";
|
||||
else if (ch == '/') result += "\\/";
|
||||
|
@ -1195,13 +1195,13 @@ void StringTest::testJSONString()
|
||||
assert (toJSON("\\", false) == "\\\\");
|
||||
assert (toJSON("\"", false) == "\\\"");
|
||||
assert (toJSON("/", false) == "\\/");
|
||||
assert (toJSON("\a", false) == "\\a");
|
||||
assert (toJSON("\a", false) == "\\u0007");
|
||||
assert (toJSON("\b", false) == "\\b");
|
||||
assert (toJSON("\f", false) == "\\f");
|
||||
assert (toJSON("\n", false) == "\\n");
|
||||
assert (toJSON("\r", false) == "\\r");
|
||||
assert (toJSON("\t", false) == "\\t");
|
||||
assert (toJSON("\v", false) == "\\v");
|
||||
assert (toJSON("\v", false) == "\\u000B");
|
||||
assert (toJSON("a", false) == "a");
|
||||
assert (toJSON("\xD0\x82", 0) == "\xD0\x82");
|
||||
assert (toJSON("\xD0\x82", Poco::JSON_ESCAPE_UNICODE) == "\\u0402");
|
||||
|
@ -83,6 +83,25 @@ void UTF8StringTest::testTransform()
|
||||
}
|
||||
|
||||
|
||||
void UTF8StringTest::testEscape()
|
||||
{
|
||||
std::string s1("A \t, a \v, and an \a walk into a |, and the barman says \xD0\x82");
|
||||
|
||||
assert (UTF8::escape(s1) == "A \\t, a \\v, and an \\a walk into a |, and the barman says \\u0402");
|
||||
assert (UTF8::escape(s1, true) == "A \\t, a \\u000B, and an \\u0007 walk into a |, and the barman says \\u0402");
|
||||
}
|
||||
|
||||
|
||||
void UTF8StringTest::testUnescape()
|
||||
{
|
||||
std::string s1("A \\t, a \\u000B, and an \\u0007 walk into a |, and the barman says \\u0402");
|
||||
std::string s2("A \\t, a \\v, and an \\a walk into a |, and the barman says \\u0402");
|
||||
|
||||
assert (UTF8::unescape(s1) == "A \t, a \v, and an \a walk into a |, and the barman says \xD0\x82");
|
||||
assert (UTF8::unescape(s2) == "A \t, a \v, and an \a walk into a |, and the barman says \xD0\x82");
|
||||
}
|
||||
|
||||
|
||||
void UTF8StringTest::setUp()
|
||||
{
|
||||
}
|
||||
@ -99,6 +118,8 @@ CppUnit::Test* UTF8StringTest::suite()
|
||||
|
||||
CppUnit_addTest(pSuite, UTF8StringTest, testCompare);
|
||||
CppUnit_addTest(pSuite, UTF8StringTest, testTransform);
|
||||
CppUnit_addTest(pSuite, UTF8StringTest, testEscape);
|
||||
CppUnit_addTest(pSuite, UTF8StringTest, testUnescape);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -27,6 +27,9 @@ public:
|
||||
void testCompare();
|
||||
void testTransform();
|
||||
|
||||
void testEscape();
|
||||
void testUnescape();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
|
@ -1930,7 +1930,6 @@ void JSONTest::testEscape0()
|
||||
|
||||
void JSONTest::testNonEscapeUnicode()
|
||||
{
|
||||
Poco::JSON::Object::Ptr json = new Poco::JSON::Object();
|
||||
std::string chinese("{ \"name\" : \"\\u4e2d\" }");
|
||||
Poco::JSON::Parser parser(new Poco::JSON::ParseHandler());
|
||||
Var result = parser.parse(chinese);
|
||||
@ -1951,6 +1950,27 @@ void JSONTest::testNonEscapeUnicode()
|
||||
object = result.extract<Object::Ptr>();
|
||||
ss.str(""); object->stringify(ss);
|
||||
assert (ss.str() == "{\"name\":\"g\xC3\xBCnter\"}");
|
||||
|
||||
Poco::JSON::Object obj1;
|
||||
std::string shortEscapeStr("String with \t");
|
||||
std::string longEscapeStr("String with \a and \v plus \t for good measure");
|
||||
obj1.set("shortEscape", shortEscapeStr);
|
||||
obj1.set("longEscape", longEscapeStr);
|
||||
|
||||
ss.str("");
|
||||
obj1.stringify(ss);
|
||||
|
||||
parser.reset();
|
||||
parser.parse(ss.str());
|
||||
result = parser.asVar();
|
||||
|
||||
assert(result.type() == typeid(Object::Ptr));
|
||||
|
||||
object = result.extract<Object::Ptr>();
|
||||
Var shortEscape = object->get("shortEscape");
|
||||
Var longEscape = object->get("longEscape");
|
||||
assert(shortEscape.convert<std::string>() == shortEscapeStr);
|
||||
assert(longEscape.convert<std::string>() == longEscapeStr);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user