mirror of
https://github.com/pocoproject/poco.git
synced 2025-02-21 06:37:42 +01:00
fix(ConfigurationView): ConfigurationView and JSON is broken for array access #3635
This commit is contained in:
parent
41f11b02bc
commit
37cb890e58
@ -32,7 +32,7 @@ class JSON_API Query
|
||||
{
|
||||
public:
|
||||
Query(const Dynamic::Var& source);
|
||||
/// Creates a Query/
|
||||
/// Creates a Query.
|
||||
///
|
||||
/// Source must be JSON Object, Array, Object::Ptr,
|
||||
/// Array::Ptr or empty Var. Any other type will trigger throwing of
|
||||
|
@ -101,6 +101,8 @@ Array& Query::findArray(const std::string& path, Array& arr) const
|
||||
Var Query::find(const std::string& path) const
|
||||
{
|
||||
Var result = _source;
|
||||
if (path.empty()) return result;
|
||||
bool found = false;
|
||||
StringTokenizer tokenizer(path, ".");
|
||||
for (const auto& token: tokenizer)
|
||||
{
|
||||
@ -134,14 +136,15 @@ Var Query::find(const std::string& path) const
|
||||
{
|
||||
Object::Ptr o = result.extract<Object::Ptr>();
|
||||
result = o->get(name);
|
||||
found = true;
|
||||
}
|
||||
else if (result.type() == typeid(Object))
|
||||
{
|
||||
Object o = result.extract<Object>();
|
||||
result = o.get(name);
|
||||
found = true;
|
||||
}
|
||||
else
|
||||
result.empty();
|
||||
else result.empty();
|
||||
|
||||
}
|
||||
|
||||
@ -165,6 +168,7 @@ Var Query::find(const std::string& path) const
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) result.empty();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1141,6 +1141,10 @@ void JSONTest::testQuery()
|
||||
|
||||
std::string firstChild = query.findValue("children[0]", "");
|
||||
assertTrue (firstChild.compare("Jonas") == 0);
|
||||
std::string secondChild = query.findValue("children[1]", "");
|
||||
assertTrue (secondChild.compare("Ellen") == 0);
|
||||
std::string thirdChild = query.findValue("children[2]", "");
|
||||
assertTrue (thirdChild.empty());
|
||||
|
||||
Poco::DynamicStruct ds = *result.extract<Object::Ptr>();
|
||||
assertTrue (ds["name"] == "Franky");
|
||||
@ -1195,6 +1199,22 @@ void JSONTest::testQuery()
|
||||
fail ("must throw");
|
||||
}
|
||||
catch (Poco::InvalidArgumentException&) { }
|
||||
|
||||
json = R"json({"foo":["bar"]})json";
|
||||
try { result = parser.parse(json); }
|
||||
catch(JSONException& jsone)
|
||||
{
|
||||
fail (jsone.message());
|
||||
}
|
||||
Query queryFoo(result);
|
||||
result = queryFoo.find("foo[0]");
|
||||
assertTrue (!result.isEmpty());
|
||||
result = queryFoo.find("foo[1]");
|
||||
assertTrue (result.isEmpty());
|
||||
result = queryFoo.find("[1]");
|
||||
assertTrue (result.isEmpty());
|
||||
result = queryFoo.find("");
|
||||
assertTrue (result.convert<std::string>() == json);
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,7 +70,7 @@ void JSONConfiguration::load(std::istream& istr)
|
||||
JSON::Parser parser;
|
||||
parser.parse(istr);
|
||||
DynamicAny result = parser.result();
|
||||
if ( result.type() == typeid(JSON::Object::Ptr) )
|
||||
if (result.type() == typeid(JSON::Object::Ptr))
|
||||
{
|
||||
_object = result.extract<JSON::Object::Ptr>();
|
||||
}
|
||||
@ -89,7 +89,7 @@ bool JSONConfiguration::getRaw(const std::string & key, std::string & value) con
|
||||
{
|
||||
JSON::Query query(_object);
|
||||
Poco::DynamicAny result = query.find(key);
|
||||
if ( ! result.isEmpty() )
|
||||
if (!result.isEmpty())
|
||||
{
|
||||
value = result.convert<std::string>();
|
||||
return true;
|
||||
@ -106,9 +106,9 @@ void JSONConfiguration::getIndexes(std::string& name, std::vector<int>& indexes)
|
||||
int firstOffset = -1;
|
||||
int offset = 0;
|
||||
RegularExpression regex("\\[([0-9]+)\\]");
|
||||
while(regex.match(name, offset, matches) > 0 )
|
||||
while(regex.match(name, offset, matches) > 0)
|
||||
{
|
||||
if ( firstOffset == -1 )
|
||||
if (firstOffset == -1)
|
||||
{
|
||||
firstOffset = static_cast<int>(matches[0].offset);
|
||||
}
|
||||
@ -117,7 +117,7 @@ void JSONConfiguration::getIndexes(std::string& name, std::vector<int>& indexes)
|
||||
offset = static_cast<int>(matches[0].offset + matches[0].length);
|
||||
}
|
||||
|
||||
if ( firstOffset != -1 )
|
||||
if (firstOffset != -1)
|
||||
{
|
||||
name = name.substr(0, firstOffset);
|
||||
}
|
||||
@ -139,9 +139,9 @@ JSON::Object::Ptr JSONConfiguration::findStart(const std::string& key, std::stri
|
||||
|
||||
DynamicAny result = currentObject->get(name);
|
||||
|
||||
if ( result.isEmpty() ) // Not found
|
||||
if (result.isEmpty()) // Not found
|
||||
{
|
||||
if ( indexes.empty() ) // We want an object, create it
|
||||
if (indexes.empty()) // We want an object, create it
|
||||
{
|
||||
JSON::Object::Ptr newObject = new JSON::Object();
|
||||
currentObject->set(name, newObject);
|
||||
@ -155,12 +155,12 @@ JSON::Object::Ptr JSONConfiguration::findStart(const std::string& key, std::stri
|
||||
for(std::vector<int>::iterator it = indexes.begin(); it != indexes.end(); ++it)
|
||||
{
|
||||
newArray = new JSON::Array();
|
||||
if ( topArray.isNull() )
|
||||
if (topArray.isNull())
|
||||
{
|
||||
topArray = newArray;
|
||||
}
|
||||
|
||||
if ( ! parentArray.isNull() )
|
||||
if (! parentArray.isNull())
|
||||
{
|
||||
parentArray->add(newArray);
|
||||
}
|
||||
@ -181,9 +181,9 @@ JSON::Object::Ptr JSONConfiguration::findStart(const std::string& key, std::stri
|
||||
}
|
||||
else // We have a value
|
||||
{
|
||||
if ( indexes.empty() ) // We want an object
|
||||
if (indexes.empty()) // We want an object
|
||||
{
|
||||
if ( result.type() == typeid(JSON::Object::Ptr) )
|
||||
if (result.type() == typeid(JSON::Object::Ptr))
|
||||
{
|
||||
currentObject = result.extract<JSON::Object::Ptr>();
|
||||
}
|
||||
@ -194,7 +194,7 @@ JSON::Object::Ptr JSONConfiguration::findStart(const std::string& key, std::stri
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( result.type() == typeid(JSON::Array::Ptr) )
|
||||
if (result.type() == typeid(JSON::Array::Ptr))
|
||||
{
|
||||
JSON::Array::Ptr arr = result.extract<JSON::Array::Ptr>();
|
||||
|
||||
@ -202,7 +202,7 @@ JSON::Object::Ptr JSONConfiguration::findStart(const std::string& key, std::stri
|
||||
{
|
||||
JSON::Array::Ptr currentArray = arr;
|
||||
arr = arr->getArray(*it);
|
||||
if ( arr.isNull() )
|
||||
if (arr.isNull())
|
||||
{
|
||||
arr = new JSON::Array();
|
||||
currentArray->add(arr);
|
||||
@ -210,7 +210,7 @@ JSON::Object::Ptr JSONConfiguration::findStart(const std::string& key, std::stri
|
||||
}
|
||||
|
||||
result = arr->get(*indexes.rbegin());
|
||||
if ( result.isEmpty() ) // Index doesn't exist
|
||||
if (result.isEmpty()) // Index doesn't exist
|
||||
{
|
||||
JSON::Object::Ptr newObject = new JSON::Object();
|
||||
arr->add(newObject);
|
||||
@ -218,7 +218,7 @@ JSON::Object::Ptr JSONConfiguration::findStart(const std::string& key, std::stri
|
||||
}
|
||||
else // Index is available
|
||||
{
|
||||
if ( result.type() == typeid(JSON::Object::Ptr) )
|
||||
if (result.type() == typeid(JSON::Object::Ptr))
|
||||
{
|
||||
currentObject = result.extract<JSON::Object::Ptr>();
|
||||
}
|
||||
@ -258,19 +258,19 @@ void JSONConfiguration::setValue(const std::string& key, const Poco::DynamicAny&
|
||||
std::vector<int> indexes;
|
||||
getIndexes(lastPart, indexes);
|
||||
|
||||
if ( indexes.empty() ) // No Array
|
||||
if (indexes.empty()) // No Array
|
||||
{
|
||||
parentObject->set(lastPart, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
DynamicAny result = parentObject->get(lastPart);
|
||||
if ( result.isEmpty() )
|
||||
if (result.isEmpty())
|
||||
{
|
||||
result = JSON::Array::Ptr(new JSON::Array());
|
||||
parentObject->set(lastPart, result);
|
||||
}
|
||||
else if ( result.type() != typeid(JSON::Array::Ptr) )
|
||||
else if (result.type() != typeid(JSON::Array::Ptr))
|
||||
{
|
||||
throw SyntaxException("Expected a JSON array");
|
||||
}
|
||||
@ -279,7 +279,7 @@ void JSONConfiguration::setValue(const std::string& key, const Poco::DynamicAny&
|
||||
for(std::vector<int>::iterator it = indexes.begin(); it != indexes.end() - 1; ++it)
|
||||
{
|
||||
JSON::Array::Ptr nextArray = arr->getArray(*it);
|
||||
if ( nextArray.isNull() )
|
||||
if (nextArray.isNull())
|
||||
{
|
||||
for(int i = static_cast<int>(arr->size()); i <= *it; ++i)
|
||||
{
|
||||
@ -335,7 +335,7 @@ void JSONConfiguration::enumerate(const std::string& key, Keys& range) const
|
||||
{
|
||||
JSON::Query query(_object);
|
||||
Poco::DynamicAny result = query.find(key);
|
||||
if ( result.type() == typeid(JSON::Object::Ptr) )
|
||||
if (result.type() == typeid(JSON::Object::Ptr))
|
||||
{
|
||||
JSON::Object::Ptr object = result.extract<JSON::Object::Ptr>();
|
||||
object->getNames(range);
|
||||
@ -358,7 +358,7 @@ void JSONConfiguration::removeRaw(const std::string& key)
|
||||
std::vector<int> indexes;
|
||||
getIndexes(lastPart, indexes);
|
||||
|
||||
if ( indexes.empty() ) // No Array
|
||||
if (indexes.empty()) // No Array
|
||||
{
|
||||
parentObject->remove(lastPart);
|
||||
}
|
||||
|
@ -113,6 +113,26 @@ void JSONConfigurationTest::testSetArrayElement()
|
||||
}
|
||||
|
||||
|
||||
void JSONConfigurationTest::testConfigurationView()
|
||||
{
|
||||
std::string json = R"json({ "foo" : [ "bar" ] })json";
|
||||
Poco::Util::JSONConfiguration config;
|
||||
std::istringstream stream(json);
|
||||
config.load(stream);
|
||||
|
||||
Poco::Util::AbstractConfiguration::Ptr pView = config.createView("foo");
|
||||
|
||||
assertTrue (pView->getString("[0]") == "bar");
|
||||
|
||||
try
|
||||
{
|
||||
pView->getString("[1]");
|
||||
fail ("must throw on index out of bounds");
|
||||
}
|
||||
catch(Poco::NotFoundException&){}
|
||||
}
|
||||
|
||||
|
||||
AbstractConfiguration::Ptr JSONConfigurationTest::allocConfiguration() const
|
||||
{
|
||||
return new JSONConfiguration;
|
||||
@ -136,6 +156,7 @@ CppUnit::Test* JSONConfigurationTest::suite()
|
||||
AbstractConfigurationTest_addTests(pSuite, JSONConfigurationTest);
|
||||
CppUnit_addTest(pSuite, JSONConfigurationTest, testLoad);
|
||||
CppUnit_addTest(pSuite, JSONConfigurationTest, testSetArrayElement);
|
||||
CppUnit_addTest(pSuite, JSONConfigurationTest, testConfigurationView);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
|
||||
void testLoad();
|
||||
void testSetArrayElement();
|
||||
void testConfigurationView();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
Loading…
x
Reference in New Issue
Block a user