mirror of
https://github.com/tristanpenman/valijson.git
synced 2025-03-02 20:30:11 +01:00
Merge pull request #40 from chubinou/qt-json
add support for Qt Json parser
This commit is contained in:
commit
4f5f8ba75d
@ -1,4 +1,4 @@
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
cmake_minimum_required (VERSION 3.1)
|
||||
project (valijson)
|
||||
|
||||
option (INSTALL_HEADERS "Install valijson Headers." FALSE)
|
||||
@ -22,6 +22,8 @@ set(Boost_USE_MULTITHREADED ON)
|
||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
||||
|
||||
find_package(Boost 1.54.0 REQUIRED)
|
||||
find_package(Qt5Core)
|
||||
|
||||
|
||||
# jsoncpp library
|
||||
add_library(jsoncpp
|
||||
@ -57,7 +59,7 @@ include_directories(
|
||||
include
|
||||
)
|
||||
|
||||
include_directories(SYSTEM
|
||||
include_directories(SYSTEM
|
||||
thirdparty/gtest-1.7.0/include
|
||||
thirdparty/json11-2016-01-26
|
||||
thirdparty/jsoncpp-0.9.4/include
|
||||
@ -65,6 +67,7 @@ include_directories(SYSTEM
|
||||
thirdparty/picojson-1.3.0
|
||||
thirdparty/nlohmann-json-1.1.0
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${Qt5Core_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# Custom schema validation example
|
||||
@ -92,6 +95,12 @@ set(TEST_SOURCES
|
||||
tests/test_poly_constraint.cpp
|
||||
)
|
||||
|
||||
if (Qt5Core_FOUND)
|
||||
list(APPEND TEST_SOURCES
|
||||
tests/test_qtjson_adapter.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# Unit tests executable
|
||||
add_executable(test_suite ${TEST_SOURCES})
|
||||
|
||||
@ -101,12 +110,17 @@ set_target_properties(test_suite
|
||||
)
|
||||
|
||||
set(TEST_LIBS gtest gtest_main jsoncpp json11)
|
||||
if (Qt5Core_FOUND)
|
||||
list(APPEND TEST_LIBS Qt5::Core)
|
||||
target_compile_definitions(test_suite PRIVATE "VALIJSON_BUILD_QT_ADAPTERS")
|
||||
endif()
|
||||
|
||||
|
||||
target_link_libraries(test_suite ${TEST_LIBS} ${Boost_LIBRARIES})
|
||||
target_link_libraries(custom_schema ${Boost_LIBRARIES})
|
||||
target_link_libraries(external_schema ${Boost_LIBRARIES})
|
||||
|
||||
endif()
|
||||
if (INSTALL_HEADERS )
|
||||
install(DIRECTORY include/ DESTINATION include )
|
||||
endif()
|
||||
|
||||
|
725
include/valijson/adapters/qtjson_adapter.hpp
Normal file
725
include/valijson/adapters/qtjson_adapter.hpp
Normal file
@ -0,0 +1,725 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Adapter implementation for the QtJson parser library.
|
||||
*
|
||||
* Include this file in your program to enable support for QtJson.
|
||||
*
|
||||
* This file defines the following classes (not in this order):
|
||||
* - QtJsonAdapter
|
||||
* - QtJsonArray
|
||||
* - QtJsonArrayValueIterator
|
||||
* - QtJsonFrozenValue
|
||||
* - QtJsonObject
|
||||
* - QtJsonObjectMember
|
||||
* - QtJsonObjectMemberIterator
|
||||
* - QtJsonValue
|
||||
*
|
||||
* 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 QtJsonAdapter. 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_QTJSON_ADAPTER_HPP
|
||||
#define __VALIJSON_ADAPTERS_QTJSON_ADAPTER_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QJsonArray>
|
||||
|
||||
|
||||
#include <valijson/adapters/adapter.hpp>
|
||||
#include <valijson/adapters/basic_adapter.hpp>
|
||||
#include <valijson/adapters/frozen_value.hpp>
|
||||
|
||||
namespace valijson {
|
||||
namespace adapters {
|
||||
|
||||
class QtJsonAdapter;
|
||||
class QtJsonArrayValueIterator;
|
||||
class QtJsonObjectMemberIterator;
|
||||
|
||||
typedef std::pair<std::string, QtJsonAdapter> QtJsonObjectMember;
|
||||
|
||||
/**
|
||||
* @brief Light weight wrapper for a QtJson array value.
|
||||
*
|
||||
* This class is light weight wrapper for a QtJson 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
|
||||
* QtJson value, assumed to be an array, so there is very little overhead
|
||||
* associated with copy construction and passing by value.
|
||||
*/
|
||||
class QtJsonArray
|
||||
{
|
||||
public:
|
||||
|
||||
typedef QtJsonArrayValueIterator const_iterator;
|
||||
typedef QtJsonArrayValueIterator iterator;
|
||||
|
||||
/// Construct a QtJsonArray referencing an empty array.
|
||||
QtJsonArray()
|
||||
: value(emptyArray())
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct a QtJsonArray referencing a specific QtJson
|
||||
* value.
|
||||
*
|
||||
* @param value reference to a QtJson value
|
||||
*
|
||||
* Note that this constructor will throw an exception if the value is not
|
||||
* an array.
|
||||
*/
|
||||
explicit QtJsonArray(const QJsonValue &value)
|
||||
: value(value.toArray())
|
||||
{
|
||||
if (!value.isArray()) {
|
||||
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 QtJson implementation.
|
||||
*/
|
||||
QtJsonArrayValueIterator 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 QtJson implementation.
|
||||
*/
|
||||
QtJsonArrayValueIterator end() const;
|
||||
|
||||
/// Return the number of elements in the array
|
||||
size_t size() const
|
||||
{
|
||||
return value.size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Return a reference to a QtJson value that is an empty array.
|
||||
*
|
||||
* Note that the value returned by this function is a singleton.
|
||||
*/
|
||||
static const QJsonArray emptyArray()
|
||||
{
|
||||
static const QJsonArray array;
|
||||
return array;
|
||||
}
|
||||
|
||||
/// Reference to the contained value
|
||||
const QJsonArray value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Light weight wrapper for a QtJson object.
|
||||
*
|
||||
* This class is light weight wrapper for a QtJson 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
|
||||
* QtJson value, assumed to be an object, so there is very little overhead
|
||||
* associated with copy construction and passing by value.
|
||||
*/
|
||||
class QtJsonObject
|
||||
{
|
||||
public:
|
||||
|
||||
typedef QtJsonObjectMemberIterator const_iterator;
|
||||
typedef QtJsonObjectMemberIterator iterator;
|
||||
|
||||
/// Construct a QtJsonObject referencing an empty object singleton.
|
||||
QtJsonObject()
|
||||
: value(emptyObject())
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct a QtJsonObject referencing a specific QtJson
|
||||
* value.
|
||||
*
|
||||
* @param value reference to a QtJson value
|
||||
*
|
||||
* Note that this constructor will throw an exception if the value is not
|
||||
* an object.
|
||||
*/
|
||||
QtJsonObject(const QJsonValue &value)
|
||||
: value(value.toObject())
|
||||
{
|
||||
if (!value.isObject()) {
|
||||
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 QtJson implementation.
|
||||
*/
|
||||
QtJsonObjectMemberIterator 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 QtJson implementation.
|
||||
*/
|
||||
QtJsonObjectMemberIterator 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
|
||||
*/
|
||||
QtJsonObjectMemberIterator find(const std::string &propertyName) const;
|
||||
|
||||
/// Returns the number of members belonging to this object.
|
||||
size_t size() const
|
||||
{
|
||||
return value.size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Return a reference to a QtJson value that is empty object.
|
||||
*
|
||||
* Note that the value returned by this function is a singleton.
|
||||
*/
|
||||
static const QJsonObject emptyObject()
|
||||
{
|
||||
static const QJsonObject object;
|
||||
return object;
|
||||
}
|
||||
|
||||
/// Reference to the contained object
|
||||
const QJsonObject value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Stores an independent copy of a QtJson value.
|
||||
*
|
||||
* This class allows a QtJson value to be stored independent of its original
|
||||
* document. QtJson makes this easy to do, as it does not perform any
|
||||
* custom memory management.
|
||||
*
|
||||
* @see FrozenValue
|
||||
*/
|
||||
class QtJsonFrozenValue: public FrozenValue
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Make a copy of a QtJson value
|
||||
*
|
||||
* @param source the QtJson value to be copied
|
||||
*/
|
||||
explicit QtJsonFrozenValue(const QJsonValue &source)
|
||||
: value(source) { }
|
||||
|
||||
virtual FrozenValue * clone() const
|
||||
{
|
||||
return new QtJsonFrozenValue(value);
|
||||
}
|
||||
|
||||
virtual bool equalTo(const Adapter &other, bool strict) const;
|
||||
|
||||
private:
|
||||
|
||||
/// Stored QtJson value
|
||||
QJsonValue value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Light weight wrapper for a QtJson value.
|
||||
*
|
||||
* This class is passed as an argument to the BasicAdapter template class,
|
||||
* and is used to provide access to a QtJson value. This class is responsible
|
||||
* for the mechanics of actually reading a QtJson 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 QtJsonValue
|
||||
{
|
||||
public:
|
||||
|
||||
/// Construct a wrapper for the empty object singleton
|
||||
QtJsonValue()
|
||||
: value(emptyObject()) { }
|
||||
|
||||
/// Construct a wrapper for a specific QtJson value
|
||||
QtJsonValue(const QJsonValue &value)
|
||||
: value(value) { }
|
||||
|
||||
/**
|
||||
* @brief Create a new QtJsonFrozenValue instance that contains the
|
||||
* value referenced by this QtJsonValue instance.
|
||||
*
|
||||
* @returns pointer to a new QtJsonFrozenValue instance, belonging to the
|
||||
* caller.
|
||||
*/
|
||||
FrozenValue * freeze() const
|
||||
{
|
||||
return new QtJsonFrozenValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Optionally return a QtJsonArray instance.
|
||||
*
|
||||
* If the referenced QtJson value is an array, this function will return
|
||||
* a std::optional containing a QtJsonArray instance referencing the
|
||||
* array.
|
||||
*
|
||||
* Otherwise it will return an empty optional.
|
||||
*/
|
||||
opt::optional<QtJsonArray> getArrayOptional() const
|
||||
{
|
||||
if (value.isArray()) {
|
||||
return opt::make_optional(QtJsonArray(value));
|
||||
}
|
||||
|
||||
return opt::optional<QtJsonArray>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the number of elements in the array
|
||||
*
|
||||
* If the referenced QtJson 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.isArray()) {
|
||||
const QJsonArray array = value.toArray();
|
||||
result = array.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getBool(bool &result) const
|
||||
{
|
||||
if (value.isBool()) {
|
||||
result = value.toBool();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getDouble(double &result) const
|
||||
{
|
||||
if (value.isDouble()) {
|
||||
result = value.toDouble();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getInteger(int64_t &result) const
|
||||
{
|
||||
if (value.isDouble()) {
|
||||
result = value.toInt();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Optionally return a QtJsonObject instance.
|
||||
*
|
||||
* If the referenced QtJson value is an object, this function will return a
|
||||
* std::optional containing a QtJsonObject instance referencing the
|
||||
* object.
|
||||
*
|
||||
* Otherwise it will return an empty optional.
|
||||
*/
|
||||
opt::optional<QtJsonObject> getObjectOptional() const
|
||||
{
|
||||
if (value.isObject()) {
|
||||
return opt::make_optional(QtJsonObject(value));
|
||||
}
|
||||
|
||||
return opt::optional<QtJsonObject>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the number of members in the object
|
||||
*
|
||||
* If the referenced QtJson 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.isObject()) {
|
||||
const QJsonObject &object = value.toObject();
|
||||
result = object.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getString(std::string &result) const
|
||||
{
|
||||
if (value.isString()) {
|
||||
result = value.toString().toStdString();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool hasStrictTypes()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isArray() const
|
||||
{
|
||||
return value.isArray();
|
||||
}
|
||||
|
||||
bool isBool() const
|
||||
{
|
||||
return value.isBool();
|
||||
}
|
||||
|
||||
bool isDouble() const
|
||||
{
|
||||
return value.isDouble();
|
||||
}
|
||||
|
||||
bool isInteger() const
|
||||
{
|
||||
//toInt returns the default value (0, 1) if the value is not a whole number
|
||||
return value.isDouble() && (value.toInt(0) == value.toInt(1));
|
||||
}
|
||||
|
||||
bool isNull() const
|
||||
{
|
||||
return value.isNull();
|
||||
}
|
||||
|
||||
bool isNumber() const
|
||||
{
|
||||
return value.isDouble();
|
||||
}
|
||||
|
||||
bool isObject() const
|
||||
{
|
||||
return value.isObject();
|
||||
}
|
||||
|
||||
bool isString() const
|
||||
{
|
||||
return value.isString();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Return a reference to an empty object singleton
|
||||
static const QJsonValue emptyObject()
|
||||
{
|
||||
static const QJsonValue object;
|
||||
return object;
|
||||
}
|
||||
|
||||
/// Reference to the contained QtJson value.
|
||||
const QJsonValue value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An implementation of the Adapter interface supporting QtJson.
|
||||
*
|
||||
* 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 QtJsonAdapter:
|
||||
public BasicAdapter<QtJsonAdapter,
|
||||
QtJsonArray,
|
||||
QtJsonObjectMember,
|
||||
QtJsonObject,
|
||||
QtJsonValue>
|
||||
{
|
||||
public:
|
||||
|
||||
/// Construct a QtJsonAdapter that contains an empty object
|
||||
QtJsonAdapter()
|
||||
: BasicAdapter() { }
|
||||
|
||||
/// Construct a QtJsonAdapter containing a specific QtJson value
|
||||
QtJsonAdapter(const QJsonValue &value)
|
||||
: BasicAdapter(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
|
||||
* QtJsonAdapter representing a value stored in the array. It has been
|
||||
* implemented using the std::iterator template.
|
||||
*
|
||||
* @see QtJsonArray
|
||||
*/
|
||||
class QtJsonArrayValueIterator:
|
||||
public std::iterator<
|
||||
std::bidirectional_iterator_tag, // bi-directional iterator
|
||||
QtJsonAdapter> // value type
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Construct a new QtJsonArrayValueIterator using an existing
|
||||
* QtJson iterator.
|
||||
*
|
||||
* @param itr QtJson iterator to store
|
||||
*/
|
||||
QtJsonArrayValueIterator(
|
||||
const QJsonArray::const_iterator &itr)
|
||||
: itr(itr) { }
|
||||
|
||||
/// Returns a QtJsonAdapter that contains the value of the current
|
||||
/// element.
|
||||
QtJsonAdapter operator*() const
|
||||
{
|
||||
return QtJsonAdapter(*itr);
|
||||
}
|
||||
|
||||
DerefProxy<QtJsonAdapter> operator->() const
|
||||
{
|
||||
return DerefProxy<QtJsonAdapter>(**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 QtJsonArrayValueIterator &other) const
|
||||
{
|
||||
return itr == other.itr;
|
||||
}
|
||||
|
||||
bool operator!=(const QtJsonArrayValueIterator &other) const
|
||||
{
|
||||
return !(itr == other.itr);
|
||||
}
|
||||
|
||||
const QtJsonArrayValueIterator& operator++()
|
||||
{
|
||||
itr++;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
QtJsonArrayValueIterator operator++(int)
|
||||
{
|
||||
QtJsonArrayValueIterator iterator_pre(itr);
|
||||
++(*this);
|
||||
return iterator_pre;
|
||||
}
|
||||
|
||||
const QtJsonArrayValueIterator& operator--()
|
||||
{
|
||||
itr--;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void advance(std::ptrdiff_t n)
|
||||
{
|
||||
itr += n;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
QJsonArray::const_iterator 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 QtJsonObjectMember representing one of the members of the object. It
|
||||
* has been implemented using the boost iterator_facade template.
|
||||
*
|
||||
* @see QtJsonObject
|
||||
* @see QtJsonObjectMember
|
||||
*/
|
||||
class QtJsonObjectMemberIterator:
|
||||
public std::iterator<
|
||||
std::bidirectional_iterator_tag, // bi-directional iterator
|
||||
QtJsonObjectMember> // value type
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Construct an iterator from a QtJson iterator.
|
||||
*
|
||||
* @param itr QtJson iterator to store
|
||||
*/
|
||||
QtJsonObjectMemberIterator(
|
||||
const QJsonObject::const_iterator &itr)
|
||||
: itr(itr) { }
|
||||
|
||||
/**
|
||||
* @brief Returns a QtJsonObjectMember that contains the key and value
|
||||
* belonging to the object member identified by the iterator.
|
||||
*/
|
||||
QtJsonObjectMember operator*() const
|
||||
{
|
||||
std::string key = itr.key().toStdString();
|
||||
return QtJsonObjectMember(key, itr.value());
|
||||
}
|
||||
|
||||
DerefProxy<QtJsonObjectMember> operator->() const
|
||||
{
|
||||
return DerefProxy<QtJsonObjectMember>(**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 QtJsonObjectMemberIterator &other) const
|
||||
{
|
||||
return itr == other.itr;
|
||||
}
|
||||
|
||||
bool operator!=(const QtJsonObjectMemberIterator &other) const
|
||||
{
|
||||
return !(itr == other.itr);
|
||||
}
|
||||
|
||||
const QtJsonObjectMemberIterator& operator++()
|
||||
{
|
||||
itr++;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
QtJsonObjectMemberIterator operator++(int)
|
||||
{
|
||||
QtJsonObjectMemberIterator iterator_pre(itr);
|
||||
++(*this);
|
||||
return iterator_pre;
|
||||
}
|
||||
|
||||
const QtJsonObjectMemberIterator& operator--(int)
|
||||
{
|
||||
itr--;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Iternal copy of the original QtJson iterator
|
||||
QJsonObject::const_iterator itr;
|
||||
};
|
||||
|
||||
/// Specialisation of the AdapterTraits template struct for QtJsonAdapter.
|
||||
template<>
|
||||
struct AdapterTraits<valijson::adapters::QtJsonAdapter>
|
||||
{
|
||||
typedef QJsonValue DocumentType;
|
||||
|
||||
static std::string adapterName()
|
||||
{
|
||||
return "QtJsonAdapter";
|
||||
}
|
||||
};
|
||||
|
||||
inline bool QtJsonFrozenValue::equalTo(const Adapter &other, bool strict) const
|
||||
{
|
||||
return QtJsonAdapter(value).equalTo(other, strict);
|
||||
}
|
||||
|
||||
inline QtJsonArrayValueIterator QtJsonArray::begin() const
|
||||
{
|
||||
return value.begin();
|
||||
}
|
||||
|
||||
inline QtJsonArrayValueIterator QtJsonArray::end() const
|
||||
{
|
||||
return value.end();
|
||||
}
|
||||
|
||||
inline QtJsonObjectMemberIterator QtJsonObject::begin() const
|
||||
{
|
||||
return value.begin();
|
||||
}
|
||||
|
||||
inline QtJsonObjectMemberIterator QtJsonObject::end() const
|
||||
{
|
||||
return value.end();
|
||||
}
|
||||
|
||||
inline QtJsonObjectMemberIterator QtJsonObject::find(
|
||||
const std::string &propertyName) const
|
||||
{
|
||||
return value.find(QString::fromStdString(propertyName));
|
||||
}
|
||||
|
||||
} // namespace adapters
|
||||
} // namespace valijson
|
||||
|
||||
#endif
|
48
include/valijson/utils/qtjson_utils.hpp
Normal file
48
include/valijson/utils/qtjson_utils.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#ifndef __VALIJSON_UTILS_QTJSON_UTILS_HPP
|
||||
#define __VALIJSON_UTILS_QTJSON_UTILS_HPP
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
|
||||
#include <valijson/utils/file_utils.hpp>
|
||||
|
||||
namespace valijson {
|
||||
namespace utils {
|
||||
|
||||
inline bool loadDocument(const std::string &path, QJsonValue &root)
|
||||
{
|
||||
// Load schema JSON from file
|
||||
QFile file(QString::fromStdString(path));
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
std::cerr << "Failed to load json from file '" << path << "'." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray data = file.readAll();
|
||||
|
||||
// Parse schema
|
||||
QJsonParseError parseError;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(data);
|
||||
if (doc.isNull()) {
|
||||
std::cerr << "qt failed to parse the document:" << std::endl
|
||||
<< parseError.errorString().toStdString() << std::endl;
|
||||
return false;
|
||||
} else if (doc.isObject()) {
|
||||
root = QJsonValue(doc.object());
|
||||
} else if (doc.isArray()) {
|
||||
root = QJsonValue(doc.array());
|
||||
} else if (doc.isEmpty()) {
|
||||
root = QJsonValue();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
} // namespace valijson
|
||||
|
||||
#endif
|
@ -20,6 +20,12 @@
|
||||
|
||||
#endif // VALIJSON_BUILD_CXX11_ADAPTERS
|
||||
|
||||
#ifdef VALIJSON_BUILD_QT_ADAPTERS
|
||||
#include <valijson/adapters/qtjson_adapter.hpp>
|
||||
#include <valijson/utils/qtjson_utils.hpp>
|
||||
|
||||
#endif // VALIJSON_BUILD_QT_ADAPTERS
|
||||
|
||||
#define TEST_DATA_DIR "../tests/data/documents/"
|
||||
|
||||
using valijson::adapters::AdapterTraits;
|
||||
@ -341,3 +347,57 @@ TEST_F(TestAdapterComparison, NlohmannJsonVsPropertyTree)
|
||||
|
||||
#endif // VALIJSON_BUILD_CXX11_ADAPTERS
|
||||
|
||||
#ifdef VALIJSON_BUILD_QT_ADAPTERS
|
||||
|
||||
TEST_F(TestAdapterComparison, QtJsonVsQtJson) {
|
||||
testComparison<
|
||||
valijson::adapters::QtJsonAdapter,
|
||||
valijson::adapters::QtJsonAdapter>();
|
||||
}
|
||||
|
||||
TEST_F(TestAdapterComparison, QtJsonVsJson11)
|
||||
{
|
||||
testComparison<
|
||||
valijson::adapters::QtJsonAdapter,
|
||||
valijson::adapters::Json11Adapter>();
|
||||
}
|
||||
|
||||
TEST_F(TestAdapterComparison, QtJsonVsJsonCpp)
|
||||
{
|
||||
testComparison<
|
||||
valijson::adapters::QtJsonAdapter,
|
||||
valijson::adapters::JsonCppAdapter>();
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TestAdapterComparison, QtJsonVsRapidJson)
|
||||
{
|
||||
testComparison<
|
||||
valijson::adapters::QtJsonAdapter,
|
||||
valijson::adapters::RapidJsonAdapter>();
|
||||
}
|
||||
|
||||
TEST_F(TestAdapterComparison, QtJsonVsRapidJsonCrtAlloc)
|
||||
{
|
||||
testComparison<
|
||||
valijson::adapters::QtJsonAdapter,
|
||||
valijson::adapters::GenericRapidJsonAdapter<
|
||||
rapidjson::GenericValue<rapidjson::UTF8<>,
|
||||
rapidjson::CrtAllocator> > >();
|
||||
}
|
||||
|
||||
TEST_F(TestAdapterComparison, QtJsonVsPicoJson)
|
||||
{
|
||||
testComparison<
|
||||
valijson::adapters::QtJsonAdapter,
|
||||
valijson::adapters::PicoJsonAdapter>();
|
||||
}
|
||||
|
||||
TEST_F(TestAdapterComparison, QtJsonVsPropertyTree)
|
||||
{
|
||||
testComparison<
|
||||
valijson::adapters::QtJsonAdapter,
|
||||
valijson::adapters::PropertyTreeAdapter>();
|
||||
}
|
||||
|
||||
#endif // VALIJSON_BUILD_QT_ADAPTERS
|
||||
|
84
tests/test_qtjson_adapter.cpp
Normal file
84
tests/test_qtjson_adapter.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <valijson/adapters/qtjson_adapter.hpp>
|
||||
|
||||
class TestQtJsonAdapter : public testing::Test
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
TEST_F(TestQtJsonAdapter, BasicArrayIteration)
|
||||
{
|
||||
const unsigned int numElements = 10;
|
||||
|
||||
// Create a picojson document that consists of an array of numbers
|
||||
QJsonArray array;
|
||||
for (unsigned int i = 0; i < numElements; i++) {
|
||||
QJsonValue value(static_cast<double>(i));
|
||||
array.push_back(value);
|
||||
}
|
||||
QJsonValue document(array);
|
||||
|
||||
// Ensure that wrapping the document preserves the array and does not allow
|
||||
// it to be cast to other types
|
||||
valijson::adapters::QtJsonAdapter 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::QtJsonAdapter 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(TestQtJsonAdapter, BasicObjectIteration)
|
||||
{
|
||||
const unsigned int numElements = 10;
|
||||
|
||||
// Create a picojson document that consists of an object that maps numeric
|
||||
// strings their corresponding numeric values
|
||||
QJsonObject object;
|
||||
for (unsigned int i = 0; i < numElements; i++) {
|
||||
QString name(QString::number(i));
|
||||
object[name] = QJsonValue(static_cast<double>(i));
|
||||
}
|
||||
QJsonValue document(object);
|
||||
|
||||
// Ensure that wrapping the document preserves the object and does not
|
||||
// allow it to be cast to other types
|
||||
valijson::adapters::QtJsonAdapter 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::QtJsonAdapter::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 );
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user