Var/JSON changes

- JSON support for Dynamic Struct and Array
- added VarIterator
- modified behavior of empty Var
This commit is contained in:
Aleksandar Fabijanic
2013-05-27 21:00:14 -05:00
parent 1f8fcaacc0
commit 38131d452d
42 changed files with 1878 additions and 308 deletions

View File

@@ -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);

View File

@@ -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.
};

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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.