Gems/AWSCore/Code/Include/Framework/JsonObjectHandler.h (112 lines of code) (raw):
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/functional.h>
#include <AzCore/JSON/reader.h>
#include <aws/core/utils/memory/stl/AWSStreamFwd.h>
namespace AWSCore
{
class JsonInputStream
{
public:
typedef char Ch;
JsonInputStream(std::istream& is) : m_is(is)
{
}
Ch Peek() const
{
int c = m_is.peek();
return c == std::char_traits<char>::eof() ? '\0' : static_cast<Ch>(c);
}
Ch Take()
{
int c = m_is.get();
return c == std::char_traits<char>::eof() ? '\0' : static_cast<Ch>(c);
}
size_t Tell() const
{
return static_cast<size_t>(m_is.tellg());
}
Ch* PutBegin()
{
AZ_Assert(false, "Not Implemented");
return nullptr;
}
void Put(Ch)
{
AZ_Assert(false, "Not Implemented");
}
void Flush()
{
AZ_Assert(false, "Not Implemented");
}
size_t PutEnd(Ch*)
{
AZ_Assert(false, "Not Implemented");
return 0;
}
AZStd::string GetContent()
{
m_is.seekg(0);
std::istreambuf_iterator<AZStd::string::value_type> eos;
AZStd::string content{ std::istreambuf_iterator<AZStd::string::value_type>(m_is),eos };
return content;
}
private:
JsonInputStream(const JsonInputStream&) = delete;
JsonInputStream& operator=(const JsonInputStream&) = delete;
std::istream& m_is;
};
class JsonReader;
/// Type of function called to update a JsonReaderHandler's state when reading
/// a JSON object.
typedef AZStd::function<bool(const char* key, JsonReader& reader)> JsonKeyHandler;
/// Type of function called to update a JsonReaderHandler's state when reading
/// a JSON array.
typedef AZStd::function<bool(JsonReader& reader)> JsonArrayHandler;
/// Default GlobalGetJsonKeyHandler template function implementation. Returns a
/// lambda that calls the following function on the object:
///
/// bool OnJsonKey(const char* key, ServiceApi::JsonReader& reader)
/// {
/// if(strcmp(key, "foo") == 0) return handler.ExpectObject(m_foo)
/// if(strcmp(key, "bar") == 0) return handler.ExpectString(m_bar)
/// return true; // ignore other keys, return false to fail
/// }
///
template<class ObjectType>
JsonKeyHandler GlobalGetJsonKeyHandler(ObjectType& object)
{
return [&object](const char* key, JsonReader& reader) {
return object.OnJsonKey(key, reader);
};
}
/// Handles the reading of JSON data.
class JsonReader
{
public:
template<class ObjectType>
static JsonKeyHandler GetJsonKeyHandler(ObjectType& object)
{
return GlobalGetJsonKeyHandler(object);
}
/// Read a JSON format object from a stream into an object. ObjectType should
/// implement the following function:
///
/// static void OnJsonKey(const char* key, JsonReader& reader)
///
/// This function will be called for each of the object's properties. It should
/// call one of the Expect methods on the state object to identify the expected
/// property type and provide a location where the property value can be stored.
template<class ObjectType>
static bool ReadObject(JsonInputStream& stream, ObjectType& object, AZStd::string& errorMessage)
{
return ReadObject(stream, GetJsonKeyHandler(object), errorMessage);
}
/// Read a JSON format object from a stream. The specified JsonKeyHandler will
/// be called for each of the object's properties. It should call one of the Expect
/// methods on the state object to identify the expected property type and provide
/// a location where the property value can be stored.
static bool ReadObject(JsonInputStream& stream, JsonKeyHandler keyHandler, AZStd::string&);
virtual bool Ignore() = 0;
/// Tell the JsonReaderHandler that a boolean value is expected and provide
/// a location where the value can be stored.
virtual bool Accept(bool& target) = 0;
/// Tell the JsonReaderHandler that a string value is expected and provide
/// a location where the value can be stored.
virtual bool Accept(AZStd::string& target) = 0;
/// Tell the JsonReaderHandler that an int value is expected and provide
/// a location where the value can be stored.
virtual bool Accept(int& target) = 0;
/// Tell the JsonReaderHandler that an unsigned value is expected and provide
/// a location where the value can be stored.
virtual bool Accept(unsigned& target) = 0;
/// Tell the JsonReaderHandler that a int64_t value is expected and provide
/// a location where the value can be stored.
virtual bool Accept(int64_t& target) = 0;
/// Tell the JsonReaderHandler that a uint64_t value is expected and provide
/// a location where the value can be stored.
virtual bool Accept(uint64_t& target) = 0;
/// Tell the JsonReaderHandler that a double value is expected and provide
/// a location where the value can be stored.
virtual bool Accept(double& target) = 0;
/// Tell the JsonReaderHandler that an object is expected and provide
/// a JsonKeyHandler function for that object.
virtual bool Accept(JsonKeyHandler keyHandler) = 0;
/// Tell the JsonReaderHandler that an object is expected and provide
/// a location where the value can be stored. ObjectType should
/// implement the following function:
///
/// static void OnJsonKey(const char* key, JsonReader& reader)
///
/// This function will be called for each of the object's properties. It should
/// call one of the Expect methods on the state object to identify the expected
/// property type and provide a location where the property value can be stored.
template<class ObjectType>
bool Accept(ObjectType& object)
{
return Accept(GlobalGetJsonKeyHandler(object));
}
virtual bool Accept(JsonArrayHandler arrayHandler) = 0;
template<class ElementType>
bool Accept(AZStd::vector<ElementType>& target)
{
target.clear();
JsonArrayHandler arrayHandler =
[&target](JsonReader& reader)
{
target.resize(target.size() + 1);
return reader.Accept(target[target.size() - 1]);
};
return Accept(arrayHandler);
}
};
} // namespace AWSCore