feat(DynamicStruct): toString() escaping #3833

This commit is contained in:
Alex Fabijanic 2022-10-13 11:50:53 +02:00
parent d11e48f851
commit a2c09c29d8
5 changed files with 65 additions and 89 deletions

View File

@ -32,6 +32,37 @@ namespace Poco {
namespace Dynamic {
template <typename S, typename I = typename S::ConstIterator>
std::string structToString(const S& data, bool wrap = true)
/// Utility function for converting DynamicStruct to std::string.
/// Set wrap to false in order to prevent string values wrapping
/// (useful to prevent JSON fragments from being treated as strings).
{
std::string val;
val.append("{ ");
I it = data.begin();
I itEnd = data.end();
if (!data.empty())
{
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(": ");
Impl::appendJSONValue(val, it->second, wrap);
++it;
}
for (; it != itEnd; ++it)
{
val.append(", ");
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(": ");
Impl::appendJSONValue(val, it->second, wrap);
}
val.append(" }");
return val;
}
template <typename K, typename M = std::map<K, Var>, typename S = std::set<K>>
class Struct
/// Struct allows to define a named collection of Var objects.
@ -226,11 +257,20 @@ public:
return it->second;
}
std::string toString() const
std::string toString(bool wrap = true) const
/// Returns the DynamicStruct as string.
///
/// To prevent unwanted string wrapping
/// (eg. when a value is JSON string),
/// `wrap` should be false. Note, however,
/// that wrap argument is of a limited utility
/// because it applies to the entire Struct,
/// so it should not be relied on when mixed content
/// (ie. plain string, which should be wrapped,
/// and JSON-as-string entries, which shouldn't)
/// is held.
{
std::string str;
Var(*this).template convert<std::string>(str);
return str;
return structToString<Data, ConstIterator>(_data, wrap);
}
private:
@ -332,26 +372,7 @@ public:
void convert(std::string& val) const
{
val.append("{ ");
ValueType::ConstIterator it = _val.begin();
ValueType::ConstIterator itEnd = _val.end();
if (!_val.empty())
{
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(": ");
Impl::appendJSONValue(val, it->second);
++it;
}
for (; it != itEnd; ++it)
{
val.append(", ");
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(": ");
Impl::appendJSONValue(val, it->second);
}
val.append(" }");
val = structToString(_val);
}
void convert(Poco::DateTime&) const
@ -518,26 +539,7 @@ public:
void convert(std::string& val) const
{
val.append("{ ");
ValueType::ConstIterator it = _val.begin();
ValueType::ConstIterator itEnd = _val.end();
if (!_val.empty())
{
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(": ");
Impl::appendJSONValue(val, it->second);
++it;
}
for (; it != itEnd; ++it)
{
val.append(", ");
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(": ");
Impl::appendJSONValue(val, it->second);
}
val.append(" }");
val = structToString(_val);
}
void convert(Poco::DateTime&) const
@ -704,26 +706,7 @@ public:
void convert(std::string& val) const
{
val.append("{ ");
ValueType::ConstIterator it = _val.begin();
ValueType::ConstIterator itEnd = _val.end();
if (!_val.empty())
{
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(": ");
Impl::appendJSONValue(val, it->second);
++it;
}
for (; it != itEnd; ++it)
{
val.append(", ");
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(": ");
Impl::appendJSONValue(val, it->second);
}
val.append(" }");
val = structToString(_val);
}
void convert(Poco::DateTime&) const
@ -890,26 +873,7 @@ public:
void convert(std::string& val) const
{
val.append("{ ");
ValueType::ConstIterator it = _val.begin();
ValueType::ConstIterator itEnd = _val.end();
if (!_val.empty())
{
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(": ");
Impl::appendJSONValue(val, it->second);
++it;
}
for (; it != itEnd; ++it)
{
val.append(", ");
Var key(it->first);
Impl::appendJSONKey(val, key);
val.append(": ");
Impl::appendJSONValue(val, it->second);
}
val.append(" }");
val = structToString(_val);
}
void convert(Poco::DateTime&) const

View File

@ -67,10 +67,12 @@ void Foundation_API appendJSONString(std::string& val, const Var& any);
/// regardless of the underlying type) and appends it to val.
void Foundation_API appendJSONValue(std::string& val, const Var& any);
void Foundation_API appendJSONValue(std::string& val, const Var& any, bool wrap = true);
/// Converts the any to a JSON value (if underlying type qualifies
/// as string - see isJSONString() - , it is wrapped into double quotes)
/// and appends it to val
/// as string - see isJSONString() - it is wrapped into double quotes)
/// and appends it to val.
/// Wrapping can be prevented (useful for appending JSON fragments) by setting
/// the wrap argument to false.
template <typename C>

View File

@ -66,7 +66,7 @@ void appendJSONKey(std::string& val, const Var& any)
}
void appendJSONValue(std::string& val, const Var& any)
void appendJSONValue(std::string& val, const Var& any, bool wrap)
{
if (any.isEmpty())
{
@ -74,7 +74,7 @@ void appendJSONValue(std::string& val, const Var& any)
}
else
{
bool isStr = isJSONString(any);
bool isStr = wrap && isJSONString(any);
if (isStr)
{
appendJSONString(val, any.convert<std::string>());

View File

@ -2286,6 +2286,14 @@ void VarTest::testOrderedDynamicStructBasics()
}
void VarTest::testDynamicStructNoEscapeString()
{
DynamicStruct aStruct;
aStruct["Birthday"] = "{ \"Day\": 12, \"Month\": \"May\", \"Year\": 2005 }";
assertEqual(aStruct.toString(false), "{ \"Birthday\": { \"Day\": 12, \"Month\": \"May\", \"Year\": 2005 } }");
}
void VarTest::testDynamicStructString()
{
DynamicStruct aStruct;
@ -3131,6 +3139,7 @@ CppUnit::Test* VarTest::suite()
CppUnit_addTest(pSuite, VarTest, testDynamicPair);
CppUnit_addTest(pSuite, VarTest, testDynamicStructBasics);
CppUnit_addTest(pSuite, VarTest, testOrderedDynamicStructBasics);
CppUnit_addTest(pSuite, VarTest, testDynamicStructNoEscapeString);
CppUnit_addTest(pSuite, VarTest, testDynamicStructString);
CppUnit_addTest(pSuite, VarTest, testOrderedDynamicStructString);
CppUnit_addTest(pSuite, VarTest, testDynamicStructInt);

View File

@ -57,6 +57,7 @@ public:
void testDynamicStructBasics();
void testOrderedDynamicStructBasics();
void testDynamicStructString();
void testDynamicStructNoEscapeString();
void testOrderedDynamicStructString();
void testDynamicStructInt();
void testOrderedDynamicStructInt();