mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-24 17:30:44 +02:00
Var/JSON changes
- JSON support for Dynamic Struct and Array - added VarIterator - modified behavior of empty Var
This commit is contained in:
@@ -55,9 +55,34 @@ class Object;
|
||||
|
||||
|
||||
class JSON_API Array
|
||||
/// Represents a JSON array. JSON array provides a representation
|
||||
/// based on shared pointers and optimized for performance. It is possible to
|
||||
/// convert object to Poco::Dynamic::Array. Conversion requires copying and therefore
|
||||
/// has performance penalty; the benefit is in improved syntax, eg:
|
||||
///
|
||||
/// // use pointers to avoid copying
|
||||
/// using namespace Poco::JSON;
|
||||
/// std::string json = "[ {\"test\" : 0}, { \"test1\" : [1, 2, 3], \"test2\" : 4 } ]";
|
||||
/// Parser parser;
|
||||
/// Var result = parser.parse(json);
|
||||
/// Array::Ptr arr = result.extract<Array::Ptr>();
|
||||
/// Object::Ptr object = arr->getObject(0); // object == {\"test\" : 0}
|
||||
/// int i = object->getValue<int>("test"); // i == 0;
|
||||
/// Object::Ptr subObject = *arr->getObject(1); // subObject == {\"test\" : 0}
|
||||
/// Array subArr::Ptr = subObject->getArray("test1"); // subArr == [1, 2, 3]
|
||||
/// i = result = subArr->get(0); // i == 1;
|
||||
///
|
||||
/// // copy/convert to Poco::Dynamic::Array
|
||||
/// Poco::Dynamic::Array da = *arr;
|
||||
/// i = da[0]["test"]; // i == 0
|
||||
/// i = da[1]["test1"][1]; // i == 2
|
||||
/// i = da[1]["test2"]; // i == 4
|
||||
///
|
||||
{
|
||||
public:
|
||||
typedef std::vector<Dynamic::Var> ValueVec;
|
||||
typedef std::vector<Dynamic::Var> ValueVec;
|
||||
typedef std::vector<Dynamic::Var>::iterator Iterator;
|
||||
typedef std::vector<Dynamic::Var>::const_iterator ConstIterator;
|
||||
typedef SharedPtr<Array> Ptr;
|
||||
|
||||
Array();
|
||||
@@ -105,6 +130,12 @@ public:
|
||||
bool isArray(unsigned int index) const;
|
||||
/// Returns true when the element is an array
|
||||
|
||||
bool isArray(const Dynamic::Var& value) const;
|
||||
/// Returns true when the element is an array
|
||||
|
||||
bool isArray(ConstIterator& value) const;
|
||||
/// Returns true when the element is an array
|
||||
|
||||
bool isNull(unsigned int index) const;
|
||||
/// Returns true when the element is null or
|
||||
/// when the element doesn't exist.
|
||||
@@ -112,6 +143,12 @@ public:
|
||||
bool isObject(unsigned int index) const;
|
||||
/// Returns true when the element is an object
|
||||
|
||||
bool isObject(const Dynamic::Var& value) const;
|
||||
/// Returns true when the element is an object
|
||||
|
||||
bool isObject(ConstIterator& value) const;
|
||||
/// Returns true when the element is an object
|
||||
|
||||
template<typename T>
|
||||
T optElement(unsigned int index, const T& def) const
|
||||
/// Returns the element at the given index. When
|
||||
@@ -144,8 +181,16 @@ public:
|
||||
void remove(unsigned int index);
|
||||
/// Removes the element on the given index.
|
||||
|
||||
operator const Poco::Dynamic::Array& () const;
|
||||
|
||||
static Poco::Dynamic::Array makeArray(const JSON::Array::Ptr& arr);
|
||||
/// Utility function for creation of array.
|
||||
|
||||
private:
|
||||
ValueVec _values;
|
||||
typedef SharedPtr<Poco::Dynamic::Array> ArrayPtr;
|
||||
|
||||
ValueVec _values;
|
||||
mutable ArrayPtr _pArray;
|
||||
};
|
||||
|
||||
|
||||
@@ -171,10 +216,22 @@ inline std::size_t Array::size() const
|
||||
inline bool Array::isArray(unsigned int index) const
|
||||
{
|
||||
Dynamic::Var value = get(index);
|
||||
return isArray(value);
|
||||
}
|
||||
|
||||
|
||||
inline bool Array::isArray(const Dynamic::Var& value) const
|
||||
{
|
||||
return value.type() == typeid(Array::Ptr);
|
||||
}
|
||||
|
||||
|
||||
inline bool Array::isArray(ConstIterator& it) const
|
||||
{
|
||||
return it!= end() && isArray(*it);
|
||||
}
|
||||
|
||||
|
||||
inline void Array::add(const Dynamic::Var& value)
|
||||
{
|
||||
_values.push_back(value);
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "Poco/JSON/JSON.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include "Poco/Dynamic/Var.h"
|
||||
#include "Poco/Dynamic/Struct.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -60,6 +61,9 @@ public:
|
||||
virtual ~Handler();
|
||||
/// Destructor
|
||||
|
||||
virtual void reset() = 0;
|
||||
/// Resets the handler state.
|
||||
|
||||
virtual void startObject() = 0;
|
||||
/// The parser has read a {, meaning a new object will be read
|
||||
|
||||
@@ -103,10 +107,11 @@ public:
|
||||
virtual void value(bool b) = 0;
|
||||
/// A boolean value is read
|
||||
|
||||
virtual void comma();
|
||||
/// A comma is read
|
||||
virtual Poco::Dynamic::Var asVar() const;
|
||||
/// Returns the result of the parser (an object, array or string),
|
||||
/// empty Var if there is no result.
|
||||
|
||||
virtual Dynamic::Var result() const;
|
||||
virtual Poco::DynamicStruct asStruct() const;
|
||||
/// Returns the result of the parser (an object, array or string),
|
||||
/// empty Var if there is no result.
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "Poco/JSON/Stringifier.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include "Poco/Dynamic/Var.h"
|
||||
#include "Poco/Dynamic/Struct.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
@@ -57,10 +58,33 @@ namespace JSON {
|
||||
|
||||
|
||||
class JSON_API Object
|
||||
/// Represents a JSON object.
|
||||
/// Represents a JSON object. JSON object provides a representation
|
||||
/// based on shared pointers and optimized for performance. It is possible to
|
||||
/// convert object to DynamicStruct. Conversion requires copying and therefore
|
||||
/// has performance penalty; the benefit is in improved syntax, eg:
|
||||
///
|
||||
/// std::string json = "{ \"test\" : { \"property\" : \"value\" } }";
|
||||
/// Parser parser;
|
||||
/// Var result = parser.parse(json);
|
||||
///
|
||||
/// // use pointers to avoid copying
|
||||
/// Object::Ptr object = result.extract<Object::Ptr>();
|
||||
/// Var test = object->get("test"); // holds { "property" : "value" }
|
||||
/// Object::Ptr subObject = test.extract<Object::Ptr>();
|
||||
/// test = subObject->get("property");
|
||||
/// std::string val = test.toString(); // val holds "value"
|
||||
///
|
||||
/// // copy/convert to Poco::DynamicStruct
|
||||
/// Poco::DynamicStruct ds = *object;
|
||||
/// val = ds["test"]["property"]; // val holds "value"
|
||||
///
|
||||
{
|
||||
public:
|
||||
typedef SharedPtr<Object> Ptr;
|
||||
typedef SharedPtr<Object> Ptr;
|
||||
typedef std::map<std::string, Dynamic::Var> ValueMap;
|
||||
typedef ValueMap::value_type ValueType;
|
||||
typedef ValueMap::iterator Iterator;
|
||||
typedef ValueMap::const_iterator ConstIterator;
|
||||
|
||||
Object(bool preserveInsertionOrder = false);
|
||||
/// Default constructor. If preserveInsertionOrder, object
|
||||
@@ -68,10 +92,31 @@ public:
|
||||
/// will be sorted by keys.
|
||||
|
||||
Object(const Object& copy);
|
||||
/// Copy constructor
|
||||
/// Copy constructor. Struct is not copied to keep the operation as
|
||||
/// efficient as possible (when needed, it will be generated upon request).
|
||||
|
||||
virtual ~Object();
|
||||
/// Destructor
|
||||
/// Destroys Object.
|
||||
|
||||
Iterator begin()
|
||||
{
|
||||
return _values.begin();
|
||||
}
|
||||
|
||||
ConstIterator begin() const
|
||||
{
|
||||
return _values.begin();
|
||||
}
|
||||
|
||||
Iterator end()
|
||||
{
|
||||
return _values.end();
|
||||
}
|
||||
|
||||
ConstIterator end() const
|
||||
{
|
||||
return _values.end();
|
||||
}
|
||||
|
||||
Dynamic::Var get(const std::string& key) const;
|
||||
/// Retrieves a property. An empty value is
|
||||
@@ -108,12 +153,18 @@ public:
|
||||
bool isArray(const std::string& key) const;
|
||||
/// Returns true when the given property contains an array
|
||||
|
||||
bool isArray(ConstIterator& it) const;
|
||||
/// Returns true when the given property contains an array
|
||||
|
||||
bool isNull(const std::string& key) const;
|
||||
/// Returns true when the given property contains a null value
|
||||
|
||||
bool isObject(const std::string& key) const;
|
||||
/// Returns true when the given property contains an object
|
||||
|
||||
bool isObject(ConstIterator& it) const;
|
||||
/// Returns true when the given property contains an object
|
||||
|
||||
template<typename T>
|
||||
T optValue(const std::string& key, const T& def) const
|
||||
/// Returns the value of a property when the property exists
|
||||
@@ -149,8 +200,13 @@ public:
|
||||
void remove(const std::string& key);
|
||||
/// Removes the property with the given key
|
||||
|
||||
private:
|
||||
static Poco::DynamicStruct makeStruct(const Object::Ptr& obj);
|
||||
/// Utility function for creation of struct.
|
||||
|
||||
operator const Poco::DynamicStruct& () const;
|
||||
/// Cast operator to Poco::DynamiStruct.
|
||||
|
||||
private:
|
||||
template <typename C>
|
||||
void doStringify(const C& container, std::ostream& out, unsigned int indent, int step) const
|
||||
{
|
||||
@@ -182,17 +238,18 @@ private:
|
||||
out << '}';
|
||||
}
|
||||
|
||||
typedef std::map<std::string, Dynamic::Var> ValueMap;
|
||||
typedef std::deque<Dynamic::Var*> KeyPtrList;
|
||||
typedef std::deque<Dynamic::Var*> KeyPtrList;
|
||||
typedef Poco::DynamicStruct::Ptr StructPtr;
|
||||
|
||||
const std::string& getKey(ValueMap::const_iterator& it) const;
|
||||
const Dynamic::Var& getValue(ValueMap::const_iterator& it) const;
|
||||
const std::string& getKey(KeyPtrList::const_iterator& it) const;
|
||||
const Dynamic::Var& getValue(KeyPtrList::const_iterator& it) const;
|
||||
|
||||
ValueMap _values;
|
||||
KeyPtrList _keys;
|
||||
bool _preserveInsOrder;
|
||||
ValueMap _values;
|
||||
KeyPtrList _keys;
|
||||
bool _preserveInsOrder;
|
||||
mutable StructPtr _pStruct;
|
||||
};
|
||||
|
||||
|
||||
@@ -206,6 +263,12 @@ inline bool Object::has(const std::string& key) const
|
||||
inline bool Object::isArray(const std::string& key) const
|
||||
{
|
||||
ValueMap::const_iterator it = _values.find(key);
|
||||
return isArray(it);
|
||||
}
|
||||
|
||||
|
||||
inline bool Object::isArray(ConstIterator& it) const
|
||||
{
|
||||
return it != _values.end() && it->second.type() == typeid(Array::Ptr);
|
||||
}
|
||||
|
||||
@@ -220,6 +283,12 @@ inline bool Object::isNull(const std::string& key) const
|
||||
inline bool Object::isObject(const std::string& key) const
|
||||
{
|
||||
ValueMap::const_iterator it = _values.find(key);
|
||||
return isObject(it);
|
||||
}
|
||||
|
||||
|
||||
inline bool Object::isObject(ConstIterator& it) const
|
||||
{
|
||||
return it != _values.end() && it->second.type() == typeid(Object::Ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,9 @@ public:
|
||||
virtual ~ParseHandler();
|
||||
/// Destroys the ParseHandler.
|
||||
|
||||
virtual void reset();
|
||||
/// Resets the handler state.
|
||||
|
||||
void startObject();
|
||||
/// Handles a '{'; a new object is started.
|
||||
|
||||
@@ -75,7 +78,7 @@ public:
|
||||
void key(const std::string& k);
|
||||
/// A key is read
|
||||
|
||||
Dynamic::Var result() const;
|
||||
Dynamic::Var asVar() const;
|
||||
/// Returns the result of the parser (an object or an array).
|
||||
|
||||
virtual void value(int v);
|
||||
@@ -117,7 +120,7 @@ private:
|
||||
};
|
||||
|
||||
|
||||
inline Dynamic::Var ParseHandler::result() const
|
||||
inline Dynamic::Var ParseHandler::asVar() const
|
||||
{
|
||||
return _result;
|
||||
}
|
||||
@@ -174,6 +177,10 @@ inline void ParseHandler::null()
|
||||
}
|
||||
|
||||
|
||||
typedef ParseHandler ParseHandler;
|
||||
//@ deprecated
|
||||
|
||||
|
||||
}} // namespace Poco::JSON
|
||||
|
||||
|
||||
|
||||
@@ -35,6 +35,29 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
/*
|
||||
Copyright (c) 2005 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef JSON_JSONParser_INCLUDED
|
||||
#define JSON_JSONParser_INCLUDED
|
||||
@@ -46,8 +69,6 @@
|
||||
#include "Poco/JSON/ParseHandler.h"
|
||||
#include "Poco/Dynamic/Var.h"
|
||||
#include "Poco/StreamTokenizer.h"
|
||||
#include <istream>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -58,7 +79,22 @@ class Source;
|
||||
|
||||
|
||||
class JSON_API Parser
|
||||
/// A class for passing JSON strings or streams.
|
||||
/// A RFC 4627 compatible class for parsing JSON strings or streams.
|
||||
///
|
||||
/// See http://www.ietf.org/rfc/rfc4627.txt for specification.
|
||||
///
|
||||
/// Usage example:
|
||||
///
|
||||
/// std::string json = "{ \"name\" : \"Franky\", \"children\" : [ \"Jonas\", \"Ellen\" ] }";
|
||||
/// Parser parser;
|
||||
/// Var result = parser.parse(json);
|
||||
/// // ... use result
|
||||
/// parser.reset();
|
||||
/// std::ostringstream ostr;
|
||||
/// PrintHandler::Ptr pHandler = new PrintHandler(ostr);
|
||||
/// parser.setHandler(pHandler);
|
||||
/// parser.parse(json); // ostr.str() == json
|
||||
///
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -170,26 +206,20 @@ public:
|
||||
enum JSONType
|
||||
{
|
||||
JSON_T_NONE = 0,
|
||||
JSON_T_ARRAY_BEGIN,
|
||||
JSON_T_ARRAY_END,
|
||||
JSON_T_OBJECT_BEGIN,
|
||||
JSON_T_OBJECT_END,
|
||||
JSON_T_INTEGER,
|
||||
JSON_T_FLOAT,
|
||||
JSON_T_NULL,
|
||||
JSON_T_TRUE,
|
||||
JSON_T_FALSE,
|
||||
JSON_T_STRING,
|
||||
JSON_T_KEY,
|
||||
JSON_T_VALUE_SEPARATOR,
|
||||
JSON_T_MAX
|
||||
};
|
||||
|
||||
static const std::size_t PARSE_BUFFER_SIZE = 3500;
|
||||
static const std::size_t PARSER_STACK_SIZE = 128;
|
||||
static const int UNLIMITED_DEPTH = -1;
|
||||
static const std::size_t JSON_PARSE_BUFFER_SIZE = 4096;
|
||||
static const std::size_t JSON_PARSER_STACK_SIZE = 128;
|
||||
static const int JSON_UNLIMITED_DEPTH = -1;
|
||||
|
||||
Parser(const Handler::Ptr& pHandler = new ParseHandler, std::size_t bufSize = PARSE_BUFFER_SIZE);
|
||||
Parser(const Handler::Ptr& pHandler = new ParseHandler, std::size_t bufSize = JSON_PARSE_BUFFER_SIZE);
|
||||
/// Constructor.
|
||||
|
||||
virtual ~Parser();
|
||||
@@ -230,10 +260,16 @@ public:
|
||||
const Handler::Ptr& getHandler();
|
||||
/// Returns the handler.
|
||||
|
||||
Dynamic::Var result() const;
|
||||
Dynamic::Var asVar() const;
|
||||
/// Returns the result of parsing;
|
||||
|
||||
Dynamic::Var result() const;
|
||||
/// Returns the result of parsing as Dynamic::Var;
|
||||
|
||||
private:
|
||||
Parser(const Parser&);
|
||||
Parser& operator = (const Parser&);
|
||||
|
||||
typedef Poco::Buffer<char> BufType;
|
||||
|
||||
bool push(int mode);
|
||||
@@ -265,7 +301,7 @@ private:
|
||||
|
||||
bool parseChar(int nextChar, Source& feeder);
|
||||
/// Called for each character (or partial character) in JSON string.
|
||||
/// It accepts UTF-8, UTF-16, or UTF-32. If it the character is accepted,
|
||||
/// It accepts UTF-8, UTF-16, or UTF-32. If the character is accepted,
|
||||
/// it returns true, otherwise false.
|
||||
|
||||
bool done();
|
||||
@@ -298,9 +334,9 @@ private:
|
||||
};
|
||||
|
||||
|
||||
inline void Parser::setAllowComments(bool sw)
|
||||
inline void Parser::setAllowComments(bool comments)
|
||||
{
|
||||
_allowComments = sw;
|
||||
_allowComments = comments;
|
||||
}
|
||||
|
||||
|
||||
@@ -310,9 +346,9 @@ inline bool Parser::getAllowComments() const
|
||||
}
|
||||
|
||||
|
||||
inline void Parser::setAllowNullByte(bool sw)
|
||||
inline void Parser::setAllowNullByte(bool nullByte)
|
||||
{
|
||||
_allowNullByte = sw;
|
||||
_allowNullByte = nullByte;
|
||||
}
|
||||
|
||||
|
||||
@@ -348,7 +384,13 @@ inline const Handler::Ptr& Parser::getHandler()
|
||||
|
||||
inline Dynamic::Var Parser::result() const
|
||||
{
|
||||
return _pHandler->result();
|
||||
return _pHandler->asVar();
|
||||
}
|
||||
|
||||
|
||||
inline Dynamic::Var Parser::asVar() const
|
||||
{
|
||||
return _pHandler->asVar();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -68,6 +68,9 @@ public:
|
||||
~PrintHandler();
|
||||
/// Destroys the PrintHandler.
|
||||
|
||||
void reset();
|
||||
/// Resets the handler state.
|
||||
|
||||
void startObject();
|
||||
/// The parser has read a '{'; a new object is started.
|
||||
/// If indent is greater than zero, a newline will be apended.
|
||||
|
||||
Reference in New Issue
Block a user