mirror of
https://github.com/tristanpenman/valijson.git
synced 2025-01-19 08:46:42 +01:00
Merge pull request #44 from drewxa/poco-json
Add support for Poco Json parser
This commit is contained in:
commit
8209db9f26
728
include/valijson/adapters/poco_json_adapter.hpp
Normal file
728
include/valijson/adapters/poco_json_adapter.hpp
Normal file
@ -0,0 +1,728 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Adapter implementation for the Poco json parser library.
|
||||
*
|
||||
* Include this file in your program to enable support for Poco json.
|
||||
*
|
||||
* This file defines the following classes (not in this order):
|
||||
* - PocoJsonAdapter
|
||||
* - PocoJsonArray
|
||||
* - PocoJsonValueIterator
|
||||
* - PocoJsonFrozenValue
|
||||
* - PocoJsonObject
|
||||
* - PocoJsonObjectMember
|
||||
* - PocoJsonObjectMemberIterator
|
||||
* - PocoJsonValue
|
||||
*
|
||||
* Due to the dependencies that exist between these classes, the ordering of
|
||||
* class declarations and definitions may be a bit confusing. The best place to
|
||||
* start is PocoJsonAdapter. This class definition is actually very small,
|
||||
* since most of the functionality is inherited from the BasicAdapter class.
|
||||
* Most of the classes in this file are provided as template arguments to the
|
||||
* inherited BasicAdapter class.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef __VALIJSON_ADAPTERS_POCO_JSON_ADAPTER_HPP
|
||||
#define __VALIJSON_ADAPTERS_POCO_JSON_ADAPTER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <Poco/JSON/Object.h>
|
||||
|
||||
#include <valijson/adapters/adapter.hpp>
|
||||
#include <valijson/adapters/basic_adapter.hpp>
|
||||
#include <valijson/adapters/frozen_value.hpp>
|
||||
|
||||
namespace valijson
|
||||
{
|
||||
namespace adapters
|
||||
{
|
||||
|
||||
class PocoJsonAdapter;
|
||||
class PocoJsonArrayValueIterator;
|
||||
class PocoJsonObjectMemberIterator;
|
||||
|
||||
typedef std::pair<std::string, PocoJsonAdapter> PocoJsonObjectMember;
|
||||
|
||||
/**
|
||||
* @brief Light weight wrapper for a PocoJson array value.
|
||||
*
|
||||
* This class is light weight wrapper for a PocoJson array. It provides a
|
||||
* minimum set of container functions and typedefs that allow it to be used as
|
||||
* an iterable container.
|
||||
*
|
||||
* An instance of this class contains a single reference to the underlying
|
||||
* PocoJson value, assumed to be an array, so there is very little overhead
|
||||
* associated with copy construction and passing by value.
|
||||
*/
|
||||
class PocoJsonArray
|
||||
{
|
||||
public:
|
||||
|
||||
typedef PocoJsonArrayValueIterator const_iterator;
|
||||
typedef PocoJsonArrayValueIterator iterator;
|
||||
|
||||
/// Construct a PocoJsonArray referencing an empty array.
|
||||
PocoJsonArray()
|
||||
: value(emptyArray())
|
||||
{ }
|
||||
|
||||
/**
|
||||
* @brief Construct a PocoJsonArray referencing a specific PocoJson
|
||||
* value.
|
||||
*
|
||||
* @param value reference to a PocoJson value
|
||||
*
|
||||
* Note that this constructor will throw an exception if the value is not
|
||||
* an array.
|
||||
*/
|
||||
PocoJsonArray(const Poco::Dynamic::Var &value)
|
||||
: value(value)
|
||||
{
|
||||
if (value.type() != typeid(Poco::JSON::Array::Ptr)) {
|
||||
throw std::runtime_error("Value is not an array.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return an iterator for the first element of the array.
|
||||
*
|
||||
* The iterator return by this function is effectively the iterator
|
||||
* returned by the underlying PocoJson implementation.
|
||||
*/
|
||||
PocoJsonArrayValueIterator begin() const;
|
||||
|
||||
/**
|
||||
* @brief Return an iterator for one-past the last element of the array.
|
||||
*
|
||||
* The iterator return by this function is effectively the iterator
|
||||
* returned by the underlying PocoJson implementation.
|
||||
*/
|
||||
PocoJsonArrayValueIterator end() const;
|
||||
|
||||
/// Return the number of elements in the array
|
||||
size_t size() const
|
||||
{
|
||||
return value.extract<Poco::JSON::Array::Ptr>()->size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Return a PocoJson value that is an empty array.
|
||||
*/
|
||||
static Poco::Dynamic::Var emptyArray()
|
||||
{
|
||||
Poco::Dynamic::Var array = Poco::JSON::Array::Ptr();
|
||||
return array;
|
||||
}
|
||||
|
||||
/// Contained value
|
||||
Poco::Dynamic::Var value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Light weight wrapper for a PocoJson object.
|
||||
*
|
||||
* This class is light weight wrapper for a PocoJson object. It provides a
|
||||
* minimum set of container functions and typedefs that allow it to be used as
|
||||
* an iterable container.
|
||||
*
|
||||
* An instance of this class contains a single reference to the underlying
|
||||
* PocoJson value, assumed to be an object, so there is very little overhead
|
||||
* associated with copy construction and passing by value.
|
||||
*/
|
||||
class PocoJsonObject
|
||||
{
|
||||
public:
|
||||
|
||||
typedef PocoJsonObjectMemberIterator const_iterator;
|
||||
typedef PocoJsonObjectMemberIterator iterator;
|
||||
|
||||
/// Construct a PocoJsonObject an empty object.
|
||||
PocoJsonObject()
|
||||
: value(emptyObject())
|
||||
{ }
|
||||
|
||||
/**
|
||||
* @brief Construct a PocoJsonObject referencing a specific PocoJson
|
||||
* value.
|
||||
*
|
||||
* @param value reference to a PocoJson value
|
||||
*
|
||||
* Note that this constructor will throw an exception if the value is not
|
||||
* an object.
|
||||
*/
|
||||
PocoJsonObject(const Poco::Dynamic::Var &value)
|
||||
: value(value)
|
||||
{
|
||||
if (value.type() != typeid(Poco::JSON::Object::Ptr)) {
|
||||
throw std::runtime_error("Value is not an object.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return an iterator for this first object member
|
||||
*
|
||||
* The iterator return by this function is effectively a wrapper around
|
||||
* the iterator value returned by the underlying PocoJson implementation.
|
||||
*/
|
||||
PocoJsonObjectMemberIterator begin() const;
|
||||
|
||||
/**
|
||||
* @brief Return an iterator for an invalid object member that indicates
|
||||
* the end of the collection.
|
||||
*
|
||||
* The iterator return by this function is effectively a wrapper around
|
||||
* the iterator value returned by the underlying PocoJson implementation.
|
||||
*/
|
||||
PocoJsonObjectMemberIterator end() const;
|
||||
|
||||
/**
|
||||
* @brief Return an iterator for the object member with the specified
|
||||
* property name.
|
||||
*
|
||||
* If an object member with the specified name does not exist, the iterator
|
||||
* returned will be the same as the iterator returned by the end() function.
|
||||
*
|
||||
* @param propertyName property name to search for
|
||||
*/
|
||||
PocoJsonObjectMemberIterator find(const std::string &propertyName) const;
|
||||
|
||||
/// Returns the number of members belonging to this object.
|
||||
size_t size() const
|
||||
{
|
||||
return value.extract<Poco::JSON::Object::Ptr>()->size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Return a PocoJson value that is empty object.
|
||||
*/
|
||||
static Poco::Dynamic::Var emptyObject()
|
||||
{
|
||||
Poco::Dynamic::Var object = Poco::JSON::Object::Ptr();
|
||||
return object;
|
||||
}
|
||||
|
||||
/// Contained value
|
||||
Poco::Dynamic::Var value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Stores an independent copy of a PocoJson value.
|
||||
*
|
||||
* This class allows a PocoJson value to be stored independent of its original
|
||||
* document. PocoJson makes this easy to do, as it does not perform any
|
||||
* custom memory management.
|
||||
*
|
||||
* @see FrozenValue
|
||||
*/
|
||||
class PocoJsonFrozenValue : public FrozenValue
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Make a copy of a PocoJson value
|
||||
*
|
||||
* @param source the PocoJson value to be copied
|
||||
*/
|
||||
explicit PocoJsonFrozenValue(const Poco::Dynamic::Var &source)
|
||||
: value(source)
|
||||
{ }
|
||||
|
||||
virtual FrozenValue * clone() const
|
||||
{
|
||||
return new PocoJsonFrozenValue(value);
|
||||
}
|
||||
|
||||
virtual bool equalTo(const Adapter &other, bool strict) const;
|
||||
|
||||
private:
|
||||
|
||||
/// Stored PocoJson value
|
||||
Poco::Dynamic::Var value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Light weight wrapper for a PocoJson value.
|
||||
*
|
||||
* This class is passed as an argument to the BasicAdapter template class,
|
||||
* and is used to provide access to a PocoJson value. This class is responsible
|
||||
* for the mechanics of actually reading a PocoJson value, whereas the
|
||||
* BasicAdapter class is responsible for the semantics of type comparisons
|
||||
* and conversions.
|
||||
*
|
||||
* The functions that need to be provided by this class are defined implicitly
|
||||
* by the implementation of the BasicAdapter template class.
|
||||
*
|
||||
* @see BasicAdapter
|
||||
*/
|
||||
class PocoJsonValue
|
||||
{
|
||||
public:
|
||||
|
||||
/// Construct a wrapper for the empty object
|
||||
PocoJsonValue()
|
||||
: value(emptyObject())
|
||||
{ }
|
||||
|
||||
/// Construct a wrapper for a specific PocoJson value
|
||||
PocoJsonValue(const Poco::Dynamic::Var& value)
|
||||
: value(value)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* @brief Create a new PocoJsonFrozenValue instance that contains the
|
||||
* value referenced by this PocoJsonValue instance.
|
||||
*
|
||||
* @returns pointer to a new PocoJsonFrozenValue instance, belonging to the
|
||||
* caller.
|
||||
*/
|
||||
FrozenValue * freeze() const
|
||||
{
|
||||
return new PocoJsonFrozenValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Optionally return a PocoJsonArray instance.
|
||||
*
|
||||
* If the referenced PocoJson value is an array, this function will return
|
||||
* a std::optional containing a PocoJsonArray instance referencing the
|
||||
* array.
|
||||
*
|
||||
* Otherwise it will return an empty optional.
|
||||
*/
|
||||
opt::optional<PocoJsonArray> getArrayOptional() const
|
||||
{
|
||||
if (value.type() == typeid(Poco::JSON::Array::Ptr)) {
|
||||
return opt::make_optional(PocoJsonArray(value));
|
||||
}
|
||||
|
||||
return opt::optional<PocoJsonArray>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the number of elements in the array
|
||||
*
|
||||
* If the referenced PocoJson value is an array, this function will
|
||||
* retrieve the number of elements in the array and store it in the output
|
||||
* variable provided.
|
||||
*
|
||||
* @param result reference to size_t to set with result
|
||||
*
|
||||
* @returns true if the number of elements was retrieved, false otherwise.
|
||||
*/
|
||||
bool getArraySize(size_t &result) const
|
||||
{
|
||||
if (value.type() == typeid(Poco::JSON::Array::Ptr)) {
|
||||
result = value.extract<Poco::JSON::Array::Ptr>()->size();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getBool(bool &result) const
|
||||
{
|
||||
if (value.isBoolean()) {
|
||||
result = value.convert<bool>();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getDouble(double &result) const
|
||||
{
|
||||
if (value.isNumeric() && !value.isInteger()) {
|
||||
result = value.convert<double>();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getInteger(int64_t &result) const
|
||||
{
|
||||
if (value.isInteger()) {
|
||||
result = value.convert<int>();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Optionally return a PocoJsonObject instance.
|
||||
*
|
||||
* If the referenced PocoJson value is an object, this function will return a
|
||||
* std::optional containing a PocoJsonObject instance referencing the
|
||||
* object.
|
||||
*
|
||||
* Otherwise it will return an empty optional.
|
||||
*/
|
||||
opt::optional<PocoJsonObject> getObjectOptional() const
|
||||
{
|
||||
if (value.type() == typeid(Poco::JSON::Object::Ptr)) {
|
||||
return opt::make_optional(PocoJsonObject(value));
|
||||
}
|
||||
|
||||
return opt::optional<PocoJsonObject>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the number of members in the object
|
||||
*
|
||||
* If the referenced PocoJson value is an object, this function will
|
||||
* retrieve the number of members in the object and store it in the output
|
||||
* variable provided.
|
||||
*
|
||||
* @param result reference to size_t to set with result
|
||||
*
|
||||
* @returns true if the number of members was retrieved, false otherwise.
|
||||
*/
|
||||
bool getObjectSize(size_t &result) const
|
||||
{
|
||||
if (value.type() == typeid(Poco::JSON::Object::Ptr)) {
|
||||
result = value.extract<Poco::JSON::Object::Ptr>()->size();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getString(std::string &result) const
|
||||
{
|
||||
if (value.isString()) {
|
||||
result = value.convert<std::string>();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool hasStrictTypes()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isArray() const
|
||||
{
|
||||
return value.type() == typeid(Poco::JSON::Array::Ptr);
|
||||
}
|
||||
|
||||
bool isBool() const
|
||||
{
|
||||
return value.isBoolean();
|
||||
}
|
||||
|
||||
bool isDouble() const
|
||||
{
|
||||
return value.isNumeric() && !value.isInteger();
|
||||
}
|
||||
|
||||
bool isInteger() const
|
||||
{
|
||||
return !isBool() && value.isInteger();
|
||||
}
|
||||
|
||||
bool isNull() const
|
||||
{
|
||||
return value.isEmpty();
|
||||
}
|
||||
|
||||
bool isNumber() const
|
||||
{
|
||||
return value.isNumeric();
|
||||
}
|
||||
|
||||
bool isObject() const
|
||||
{
|
||||
return value.type() == typeid(Poco::JSON::Object::Ptr);
|
||||
}
|
||||
|
||||
bool isString() const
|
||||
{
|
||||
return value.isString();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Return an empty object
|
||||
static Poco::Dynamic::Var emptyObject()
|
||||
{
|
||||
Poco::Dynamic::Var object = Poco::JSON::Object::Ptr();
|
||||
return object;
|
||||
}
|
||||
|
||||
/// Contained value
|
||||
Poco::Dynamic::Var value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An implementation of the Adapter interface supporting PocoJson.
|
||||
*
|
||||
* This class is defined in terms of the BasicAdapter template class, which
|
||||
* helps to ensure that all of the Adapter implementations behave consistently.
|
||||
*
|
||||
* @see Adapter
|
||||
* @see BasicAdapter
|
||||
*/
|
||||
class PocoJsonAdapter :
|
||||
public BasicAdapter<PocoJsonAdapter,
|
||||
PocoJsonArray,
|
||||
PocoJsonObjectMember,
|
||||
PocoJsonObject,
|
||||
PocoJsonValue>
|
||||
{
|
||||
public:
|
||||
/// Construct a PocoJsonAdapter that contains an empty object
|
||||
PocoJsonAdapter()
|
||||
: BasicAdapter()
|
||||
{ }
|
||||
|
||||
/// Construct a PocoJsonAdapter containing a specific Poco Json object
|
||||
PocoJsonAdapter(const Poco::Dynamic::Var &value)
|
||||
: BasicAdapter(PocoJsonValue {value})
|
||||
{ }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class for iterating over values held in a JSON array.
|
||||
*
|
||||
* This class provides a JSON array iterator that dereferences as an instance of
|
||||
* PocoJsonAdapter representing a value stored in the array. It has been
|
||||
* implemented using the boost iterator_facade template.
|
||||
*
|
||||
* @see PocoJsonArray
|
||||
*/
|
||||
class PocoJsonArrayValueIterator :
|
||||
public std::iterator<
|
||||
std::bidirectional_iterator_tag, // bi-directional iterator
|
||||
PocoJsonAdapter> // value type
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Construct a new PocoJsonArrayValueIterator using an existing
|
||||
* PocoJson iterator.
|
||||
*
|
||||
* @param itr PocoJson iterator to store
|
||||
*/
|
||||
PocoJsonArrayValueIterator(const Poco::JSON::Array::ConstIterator &itr)
|
||||
: itr(itr)
|
||||
{ }
|
||||
|
||||
/// Returns a PocoJsonAdapter that contains the value of the current
|
||||
/// element.
|
||||
PocoJsonAdapter operator*() const
|
||||
{
|
||||
return PocoJsonAdapter(*itr);
|
||||
}
|
||||
|
||||
DerefProxy<PocoJsonAdapter> operator->() const
|
||||
{
|
||||
return DerefProxy<PocoJsonAdapter>(**this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare this iterator against another iterator.
|
||||
*
|
||||
* Note that this directly compares the iterators, not the underlying
|
||||
* values, and assumes that two identical iterators will point to the same
|
||||
* underlying object.
|
||||
*
|
||||
* @param other iterator to compare against
|
||||
*
|
||||
* @returns true if the iterators are equal, false otherwise.
|
||||
*/
|
||||
bool operator==(const PocoJsonArrayValueIterator &other) const
|
||||
{
|
||||
return itr == other.itr;
|
||||
}
|
||||
|
||||
bool operator!=(const PocoJsonArrayValueIterator &other) const
|
||||
{
|
||||
return !(itr == other.itr);
|
||||
}
|
||||
|
||||
const PocoJsonArrayValueIterator& operator++()
|
||||
{
|
||||
itr++;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
PocoJsonArrayValueIterator operator++(int)
|
||||
{
|
||||
PocoJsonArrayValueIterator iterator_pre(itr);
|
||||
++(*this);
|
||||
return iterator_pre;
|
||||
}
|
||||
|
||||
const PocoJsonArrayValueIterator& operator--()
|
||||
{
|
||||
itr--;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void advance(std::ptrdiff_t n)
|
||||
{
|
||||
itr += n;
|
||||
}
|
||||
|
||||
private:
|
||||
Poco::JSON::Array::ConstIterator itr;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Class for iterating over the members belonging to a JSON object.
|
||||
*
|
||||
* This class provides a JSON object iterator that dereferences as an instance
|
||||
* of PocoJsonObjectMember representing one of the members of the object. It
|
||||
* has been implemented using the boost iterator_facade template.
|
||||
*
|
||||
* @see PocoJsonObject
|
||||
* @see PocoJsonObjectMember
|
||||
*/
|
||||
class PocoJsonObjectMemberIterator :
|
||||
public std::iterator<
|
||||
std::bidirectional_iterator_tag, // bi-directional iterator
|
||||
PocoJsonObjectMember> // value type
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Construct an iterator from a PocoJson iterator.
|
||||
*
|
||||
* @param itr PocoJson iterator to store
|
||||
*/
|
||||
PocoJsonObjectMemberIterator(const Poco::JSON::Object::ConstIterator &itr)
|
||||
: itr(itr)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* @brief Returns a PocoJsonObjectMember that contains the key and value
|
||||
* belonging to the object member identified by the iterator.
|
||||
*/
|
||||
PocoJsonObjectMember operator*() const
|
||||
{
|
||||
return PocoJsonObjectMember(itr->first, itr->second);
|
||||
}
|
||||
|
||||
DerefProxy<PocoJsonObjectMember> operator->() const
|
||||
{
|
||||
return DerefProxy<PocoJsonObjectMember>(**this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare this iterator with another iterator.
|
||||
*
|
||||
* Note that this directly compares the iterators, not the underlying
|
||||
* values, and assumes that two identical iterators will point to the same
|
||||
* underlying object.
|
||||
*
|
||||
* @param other Iterator to compare with
|
||||
*
|
||||
* @returns true if the underlying iterators are equal, false otherwise
|
||||
*/
|
||||
bool operator==(const PocoJsonObjectMemberIterator &other) const
|
||||
{
|
||||
return itr == other.itr;
|
||||
}
|
||||
|
||||
bool operator!=(const PocoJsonObjectMemberIterator &other) const
|
||||
{
|
||||
return !(itr == other.itr);
|
||||
}
|
||||
|
||||
const PocoJsonObjectMemberIterator& operator++()
|
||||
{
|
||||
itr++;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
PocoJsonObjectMemberIterator operator++(int)
|
||||
{
|
||||
PocoJsonObjectMemberIterator iterator_pre(itr);
|
||||
++(*this);
|
||||
return iterator_pre;
|
||||
}
|
||||
|
||||
const PocoJsonObjectMemberIterator& operator--()
|
||||
{
|
||||
itr--;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Iternal copy of the original PocoJson iterator
|
||||
Poco::JSON::Object::ConstIterator itr;
|
||||
};
|
||||
|
||||
/// Specialisation of the AdapterTraits template struct for PocoJsonAdapter.
|
||||
template<>
|
||||
struct AdapterTraits<valijson::adapters::PocoJsonAdapter>
|
||||
{
|
||||
typedef Poco::Dynamic::Var DocumentType;
|
||||
|
||||
static std::string adapterName()
|
||||
{
|
||||
return "PocoJsonAdapter";
|
||||
}
|
||||
};
|
||||
|
||||
inline PocoJsonArrayValueIterator PocoJsonArray::begin() const
|
||||
{
|
||||
return value.extract<Poco::JSON::Array::Ptr>()->begin();
|
||||
}
|
||||
|
||||
inline PocoJsonArrayValueIterator PocoJsonArray::end() const
|
||||
{
|
||||
return value.extract<Poco::JSON::Array::Ptr>()->end();
|
||||
}
|
||||
|
||||
inline PocoJsonObjectMemberIterator PocoJsonObject::begin() const
|
||||
{
|
||||
return value.extract<Poco::JSON::Object::Ptr>()->begin();
|
||||
}
|
||||
|
||||
inline PocoJsonObjectMemberIterator PocoJsonObject::end() const
|
||||
{
|
||||
return value.extract<Poco::JSON::Object::Ptr>()->end();
|
||||
}
|
||||
|
||||
inline PocoJsonObjectMemberIterator PocoJsonObject::find(
|
||||
const std::string &propertyName) const
|
||||
{
|
||||
auto& ptr = value.extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
auto it = std::find_if(ptr->begin(), ptr->end(),
|
||||
[&propertyName](const Poco::JSON::Object::ValueType& p)
|
||||
{
|
||||
return p.first == propertyName;
|
||||
});
|
||||
return it;
|
||||
}
|
||||
|
||||
inline bool PocoJsonFrozenValue::equalTo(const Adapter &other, bool strict) const
|
||||
{
|
||||
return PocoJsonAdapter(value).equalTo(other, strict);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace adapters
|
||||
} // namespace valijson
|
||||
|
||||
#endif // __VALIJSON_ADAPTERS_POCO_JSON_ADAPTER_HPP
|
||||
|
38
include/valijson/utils/poco_json_utils.hpp
Normal file
38
include/valijson/utils/poco_json_utils.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#ifndef VALIJSON_POCO_JSON_UTILS_HPP
|
||||
#define VALIJSON_POCO_JSON_UTILS_HPP
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <Poco/JSON/Object.h>
|
||||
#include <Poco/JSON/Parser.h>
|
||||
#include <valijson/utils/file_utils.hpp>
|
||||
|
||||
namespace valijson {
|
||||
namespace utils {
|
||||
|
||||
inline bool loadDocument(const std::string &path, Poco::Dynamic::Var &document) {
|
||||
// Load schema JSON from file
|
||||
std::string file;
|
||||
if (!loadFile(path, file)) {
|
||||
std::cerr << "Failed to load json from file '" << path << "'."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse schema
|
||||
try {
|
||||
document = Poco::JSON::Parser().parse(file);
|
||||
} catch (std::invalid_argument const& exception) {
|
||||
std::cerr << "nlohmann::json failed to parse the document\n"
|
||||
<< "Parse error:" << exception.what() << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
} // namespace valijson
|
||||
|
||||
#endif //VALIJSON_POCO_JSON_UTILS_HPP
|
89
tests/test_poco_json_adapter.cpp
Normal file
89
tests/test_poco_json_adapter.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#ifdef VALIJSON_BUILD_POCO_ADAPTERS
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <valijson/adapters/poco_json_adapter.hpp>
|
||||
|
||||
class TestPocoJsonAdapter : public testing::Test
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
TEST_F(TestPocoJsonAdapter, BasicArrayIteration)
|
||||
{
|
||||
const unsigned int numElements = 10;
|
||||
|
||||
// Create a Json document that consists of an array of numbers
|
||||
Poco::JSON::Array::Ptr documentImpl = new Poco::JSON::Array();
|
||||
|
||||
for (unsigned int i = 0; i < numElements; i++) {
|
||||
documentImpl->set(i, static_cast<double>(i));
|
||||
}
|
||||
|
||||
Poco::Dynamic::Var document = documentImpl;
|
||||
|
||||
// Ensure that wrapping the document preserves the array and does not allow
|
||||
// it to be cast to other types
|
||||
valijson::adapters::PocoJsonAdapter adapter(document);
|
||||
ASSERT_NO_THROW( adapter.getArray() );
|
||||
ASSERT_ANY_THROW( adapter.getBool() );
|
||||
ASSERT_ANY_THROW( adapter.getDouble() );
|
||||
ASSERT_ANY_THROW( adapter.getObject() );
|
||||
ASSERT_ANY_THROW( adapter.getString() );
|
||||
|
||||
// Ensure that the array contains the expected number of elements
|
||||
EXPECT_EQ( numElements, adapter.getArray().size() );
|
||||
|
||||
// Ensure that the elements are returned in the order they were inserted
|
||||
unsigned int expectedValue = 0;
|
||||
for (const valijson::adapters::PocoJsonAdapter value : adapter.getArray()) {
|
||||
ASSERT_TRUE( value.isNumber() );
|
||||
EXPECT_EQ( double(expectedValue), value.getDouble() );
|
||||
expectedValue++;
|
||||
}
|
||||
|
||||
// Ensure that the correct number of elements were iterated over
|
||||
EXPECT_EQ(numElements, expectedValue);
|
||||
}
|
||||
|
||||
TEST_F(TestPocoJsonAdapter, BasicObjectIteration)
|
||||
{
|
||||
const unsigned int numElements = 10;
|
||||
|
||||
// Create a DropBoxJson document that consists of an object that maps numeric
|
||||
// strings their corresponding numeric values
|
||||
Poco::JSON::Object::Ptr documentImpl = new Poco::JSON::Object;
|
||||
|
||||
for (uint32_t i = 0; i < numElements; i++) {
|
||||
documentImpl->set(std::to_string(i), static_cast<double>(i));
|
||||
}
|
||||
|
||||
Poco::Dynamic::Var document = documentImpl;
|
||||
|
||||
// Ensure that wrapping the document preserves the object and does not
|
||||
// allow it to be cast to other types
|
||||
valijson::adapters::PocoJsonAdapter adapter(document);
|
||||
ASSERT_NO_THROW( adapter.getObject() );
|
||||
ASSERT_ANY_THROW( adapter.getArray() );
|
||||
ASSERT_ANY_THROW( adapter.getBool() );
|
||||
ASSERT_ANY_THROW( adapter.getDouble() );
|
||||
ASSERT_ANY_THROW( adapter.getString() );
|
||||
|
||||
// Ensure that the object contains the expected number of members
|
||||
EXPECT_EQ( numElements, adapter.getObject().size() );
|
||||
|
||||
// Ensure that the members are returned in the order they were inserted
|
||||
unsigned int expectedValue = 0;
|
||||
for (const valijson::adapters::PocoJsonAdapter::ObjectMember member : adapter.getObject()) {
|
||||
ASSERT_TRUE( member.second.isNumber() );
|
||||
EXPECT_EQ( std::to_string(expectedValue), member.first );
|
||||
EXPECT_EQ( double(expectedValue), member.second.getDouble() );
|
||||
expectedValue++;
|
||||
}
|
||||
|
||||
// Ensure that the correct number of elements were iterated over
|
||||
EXPECT_EQ( numElements, expectedValue );
|
||||
}
|
||||
|
||||
#endif // VALIJSON_BUILD_POCO_ADAPTERS
|
||||
|
@ -20,6 +20,11 @@
|
||||
#include <valijson/utils/json11_utils.hpp>
|
||||
#endif // VALIJSON_BUILD_CXX11_ADAPTERS
|
||||
|
||||
#ifdef VALIJSON_BUILD_POCO_ADAPTERS
|
||||
#include <valijson/adapters/poco_json_adapter.hpp>
|
||||
#include <valijson/utils/poco_json_utils.hpp>
|
||||
#endif // VALIJSON_BUILD_POCO_ADAPTERS
|
||||
|
||||
#define REMOTES_DIR "../thirdparty/JSON-Schema-Test-Suite/remotes/"
|
||||
|
||||
#define TEST_SUITE_DIR "../thirdparty/JSON-Schema-Test-Suite/tests/"
|
||||
@ -170,6 +175,10 @@ protected:
|
||||
#ifdef VALIJSON_BUILD_CXX11_ADAPTERS
|
||||
processTestFile<valijson::adapters::Json11Adapter>(testFile, version);
|
||||
#endif // VALIJSON_BUILD_CXX11_ADAPTERS
|
||||
|
||||
#ifdef VALIJSON_BUILD_POCO_ADAPTERS
|
||||
processTestFile<valijson::adapters::PocoJsonAdapter>(testFile, version);
|
||||
#endif // VALIJSON_BUILD_POCO_ADAPTERS
|
||||
}
|
||||
|
||||
void processDraft3TestFile(const std::string &testFile)
|
||||
|
Loading…
x
Reference in New Issue
Block a user