Last active
December 23, 2019 16:38
-
-
Save azaika/c2d884b9c54b7de725841b1259c01e7e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# pragma once | |
# include <memory> | |
# include <variant> | |
# include "Fwd.hpp" | |
# include "TextReader.hpp" | |
# include "TextWriter.hpp" | |
# include "Array.hpp" | |
namespace s3d | |
{ | |
// Fwd.hpp に書く | |
////////////////////////////////////////////////////// | |
// | |
// JSONData.hpp | |
// | |
struct JSONItem; | |
class JSONDataIterator; | |
class JSONDataConstIterator; | |
class JSONData; | |
namespace detail | |
{ | |
struct JSONDataIteratorDetail; | |
struct JSONDataConstIteratorDetail; | |
struct JSONDataDetail; | |
} | |
class JSONDataIterator | |
{ | |
private: | |
std::shared_ptr<detail::JSONDataIteratorDetail> m_detail; | |
public: | |
JSONDataIterator() = default; | |
JSONDataIterator(const JSONDataIterator&); | |
explicit JSONDataIterator(const detail::JSONDataIteratorDetail&); | |
JSONDataIterator& operator = (const JSONDataIterator& rhs) | |
{ | |
JSONDataIterator tmp = rhs; | |
m_detail = std::move(tmp.m_detail); | |
return *this; | |
} | |
JSONDataIterator& operator++(); | |
JSONDataIterator operator++(int); | |
[[nodiscard]] JSONDataIterator operator +(size_t index) const; | |
[[nodiscard]] JSONItem operator *() const; | |
[[nodiscard]] String key() const; | |
[[nodiscard]] JSONData value() const; | |
[[nodiscard]] bool operator ==(const JSONDataIterator& other) const noexcept; | |
[[nodiscard]] bool operator !=(const JSONDataIterator& other) const noexcept | |
{ | |
return !(*this == other); | |
} | |
}; | |
class JSONDataConstIterator | |
{ | |
private: | |
std::shared_ptr<detail::JSONDataConstIteratorDetail> m_detail; | |
public: | |
JSONDataConstIterator() = default; | |
JSONDataConstIterator(const JSONDataConstIterator&); | |
explicit JSONDataConstIterator(const detail::JSONDataConstIteratorDetail&); | |
JSONDataConstIterator& operator = (const JSONDataConstIterator& rhs) | |
{ | |
JSONDataConstIterator tmp = rhs; | |
m_detail = std::move(tmp.m_detail); | |
return *this; | |
} | |
JSONDataConstIterator& operator++(); | |
JSONDataConstIterator operator++(int); | |
[[nodiscard]] JSONDataConstIterator operator +(size_t index) const; | |
[[nodiscard]] const JSONItem operator *() const; | |
[[nodiscard]] String key() const; | |
[[nodiscard]] const JSONData value() const; | |
[[nodiscard]] bool operator ==(const JSONDataConstIterator& other) const noexcept; | |
[[nodiscard]] bool operator !=(const JSONDataConstIterator& other) const noexcept | |
{ | |
return !(*this == other); | |
} | |
}; | |
class JSONData | |
{ | |
private: | |
std::shared_ptr<detail::JSONDataDetail> m_data; | |
Optional<int64> getOptInt64() const; | |
Optional<double> getOptDouble() const; | |
Optional<String> getOptString() const; | |
Optional<bool> getOptBool() const; | |
public: | |
using reference = JSONData; | |
using const_reference = const JSONData; | |
using iterator = JSONDataIterator; | |
using const_iterator = JSONDataConstIterator; | |
JSONData() : JSONData(nullptr) {}; | |
JSONData(JSONData&&) = default; | |
JSONData(const JSONData& data); | |
explicit JSONData(const detail::JSONDataDetail&); | |
JSONData(std::nullptr_t); | |
JSONData(int64 value); | |
JSONData(uint64 value); | |
JSONData(double value); | |
JSONData(bool value); | |
template <class Type, std::enable_if_t<std::is_integral_v<Type>> * = nullptr> | |
JSONData(Type value) : JSONData(static_cast<int64>(value)) {} | |
JSONData(StringView value); | |
template <class Type, std::enable_if_t<std::is_constructible_v<StringView, Type>> * = nullptr> | |
JSONData(Type&& value) : JSONData(StringView(std::forward<Type>(value))) {} | |
JSONData(const Array<JSONData>& array); | |
template <class Type, std::enable_if_t<!std::is_same_v<std::decay_t<Type>, JSONData> && std::is_constructible_v<JSONData, Type>> * = nullptr> | |
JSONData(const Array<Type>& arr) : JSONData(arr.map([](auto&& v) { return JSONData(v); })) {} | |
template <class Type, std::enable_if_t<std::is_constructible_v<JSONData, Type>> * = nullptr> | |
JSONData(const std::initializer_list<Type>& list) : JSONData(Array(list)) {} | |
JSONData(const std::initializer_list<std::pair<String, JSONData>>& list); | |
[[nodiscard]] bool isEmpty() const { return !m_data; } | |
[[nodiscard]] explicit operator bool() const { return !isEmpty(); } | |
[[nodiscard]] bool isNull() const; | |
[[nodiscard]] bool isBool() const; | |
[[nodiscard]] bool isNumber() const; | |
[[nodiscard]] bool isInteger() const; | |
[[nodiscard]] bool isUnsigned() const; | |
[[nodiscard]] bool isFloat() const; | |
[[nodiscard]] bool isString() const; | |
[[nodiscard]] bool isArray() const; | |
[[nodiscard]] bool isObject() const; | |
[[nodiscard]] JSONValueType getType() const; | |
[[nodiscard]] bool hasMember(StringView name) const; | |
[[nodiscard]] String getString() const; | |
template <class Type> | |
[[nodiscard]] Type get() const | |
{ | |
return getOpt<Type>().value_or(Type()); | |
} | |
template <class Type, class U> | |
[[nodiscard]] Type getOr(U&& defaultValue) const | |
{ | |
return getOpt<Type>().value_or(std::forward<U>(defaultValue)); | |
} | |
template <class Type> | |
[[nodiscard]] Optional<Type> getOpt() const | |
{ | |
return getOpt_<Type>(); | |
} | |
template <> | |
[[nodiscard]] Optional<String> getOpt<String>() const | |
{ | |
return getOptString(); | |
} | |
template <> | |
[[nodiscard]] Optional<int64> getOpt<int64>() const | |
{ | |
return getOptInt64(); | |
} | |
template <> | |
[[nodiscard]] Optional<double> getOpt<double>() const | |
{ | |
return getOptDouble(); | |
} | |
template <> | |
[[nodiscard]] Optional<bool> getOpt<bool>() const | |
{ | |
return getOptBool(); | |
} | |
reference operator [](StringView name); | |
[[nodiscard]] const_reference operator [](StringView name) const; | |
reference operator [](size_t idx); | |
[[nodiscard]] const_reference operator [](size_t idx) const; | |
// get reference to the child by JSON pointer | |
reference access(StringView jsonPointer); | |
[[nodiscard]] const_reference access(StringView jsonPointer) const; | |
[[nodiscard]] iterator begin(); | |
[[nodiscard]] const_iterator begin() const; | |
[[nodiscard]] iterator end(); | |
[[nodiscard]] const_iterator end() const; | |
[[nodiscard]] size_t size() const; | |
[[nodiscard]] String format(char32 ch = U' ', size_t count = 2) const; | |
[[nodiscard]] String formatMinimum() const; | |
bool parse(StringView str); | |
bool load(FilePathView path); | |
template <class Reader, std::enable_if_t<std::is_base_of_v<IReader, Reader>> * = nullptr> | |
bool load(Reader&& reader) | |
{ | |
return load(std::make_shared<Reader>(std::move(reader))); | |
} | |
bool load(const std::shared_ptr<IReader>& reader) | |
{ | |
TextReader textReader(reader); | |
if (!textReader) | |
{ | |
*this = nullptr; | |
return false; | |
} | |
return parse(textReader.readAll()); | |
} | |
bool save(FilePathView path) const | |
{ | |
TextWriter writer(path); | |
if (!writer) | |
{ | |
return false; | |
} | |
writer.write(format()); | |
return true; | |
} | |
bool saveMinimum(FilePathView path) const | |
{ | |
TextWriter writer(path); | |
if (!writer) | |
{ | |
return false; | |
} | |
writer.write(formatMinimum()); | |
return true; | |
} | |
JSONData& operator = (int64 value); | |
JSONData& operator = (uint64 value); | |
JSONData& operator = (double value); | |
JSONData& operator = (bool value); | |
template <class Type, std::enable_if_t<std::is_integral_v<Type>> * = nullptr> | |
JSONData& operator = (Type value) | |
{ | |
*this = static_cast<int64>(value); | |
return *this; | |
} | |
JSONData& operator = (StringView str); | |
template <class Type, std::enable_if_t<std::is_constructible_v<StringView, Type>> * = nullptr> | |
JSONData& operator = (Type&& value) | |
{ | |
*this = StringView(std::forward<Type>(value)); | |
return *this; | |
} | |
JSONData& operator = (const Array<JSONData>& array); | |
template <class Type, std::enable_if_t<!std::is_same_v<std::decay_t<Type>, JSONData> && std::is_constructible_v<JSONData, Type>> * = nullptr> | |
JSONData& operator = (const Array<Type>& arr) | |
{ | |
m_data = arr.map([](auto&& v) { return JSONData(v); }); | |
return *this; | |
} | |
template <class Type, std::enable_if_t<std::is_constructible_v<JSONData, Type>> * = nullptr> | |
JSONData& operator = (const std::initializer_list<Type>& list) | |
{ | |
m_data = Array(list); | |
return *this; | |
} | |
JSONData& operator = (const std::initializer_list<std::pair<String, JSONData>>& list); | |
}; | |
struct JSONItem | |
{ | |
String key; | |
JSONData value; | |
}; | |
JSONData LoadJSON(FilePathView path); | |
void Formatter(FormatData& formatData, const JSONData& json); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# include <Siv3D.hpp> // OpenSiv3D v0.4.2 | |
void Main() | |
{ | |
JSONData json = LoadJSON(U"example/config/config.json"); | |
// これでも OK | |
json.load(U"example/config/config.json"); | |
if (!json) // もし読み込みに失敗したら | |
{ | |
throw Error(U"Failed to load `config.json`"); | |
} | |
// アクセス | |
Print << json[U"Window"][U"title"]; | |
// Optional を使ったアクセス | |
if (auto&& bg = json[U"Scene"][U"background"].getOpt<String>()) | |
{ | |
Print << *bg; | |
} | |
// JSON Pointer を使ったアクセス | |
Print << json.access(U"/Items/1"); | |
// 再代入 | |
json = { | |
{U"Window", { | |
{U"title", U"My application"}, | |
{U"width", 800}, | |
{U"height", 600}, | |
{U"sizable", false} | |
}}, | |
{U"Scene", { | |
{U"background", Format(ColorF(0.8, 0.9, 1.0))}, | |
}}, | |
{U"Array", { | |
{11, 22, 33, 44, 55} | |
}}, | |
{U"Items", { | |
{{ | |
{U"label", U"Forest"}, | |
{U"pos", { | |
{U"x", 100}, | |
{U"y", 100} | |
}} | |
}, | |
{ | |
{U"label", U"Ocean"}, | |
{U"pos", { | |
{U"x", 300}, | |
{U"y", 200} | |
}} | |
}, | |
{ | |
{U"label", U"Mountain"}, | |
{U"pos", { | |
{U"x", 500}, | |
{U"y", 100} | |
}} | |
}} | |
}} | |
}; | |
// for ループ可能 | |
for (auto&& j : json) | |
{ | |
// size() 関数で value の持つ要素数が分かる | |
Print << U"size({}) = {}"_fmt(j.key, j.value.size()); | |
} | |
// format() で文字列化可能 | |
Print << json[U"Items"][2][U"pos"].format(); | |
// 保存 | |
json.save(U"test.json"); | |
// 不要なスペースを消して保存 | |
json.saveMinimum(U"minimum.json"); | |
while (System::Update()) | |
{ | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//----------------------------------------------- | |
// | |
// This file is part of the Siv3D Engine. | |
// | |
// Copyright (c) 2008-2019 Ryo Suzuki | |
// Copyright (c) 2016-2019 OpenSiv3D Project | |
// | |
// Licensed under the MIT License. | |
// | |
//----------------------------------------------- | |
# include <nlohmann/json.hpp> | |
# include <Siv3D/JSONData.hpp> | |
# include <Siv3D/JSONReader.hpp> | |
# include <Siv3D/TextReader.hpp> | |
# include <Siv3D/Array.hpp> | |
# include <Siv3D/Error.hpp> | |
namespace s3d | |
{ | |
namespace detail | |
{ | |
struct JSONDataIteratorDetail | |
{ | |
nlohmann::json::iterator it; | |
JSONDataIteratorDetail() = default; | |
JSONDataIteratorDetail(nlohmann::json::iterator _it) | |
: it(_it) {} | |
}; | |
struct JSONDataConstIteratorDetail | |
{ | |
nlohmann::json::const_iterator it; | |
JSONDataConstIteratorDetail() = default; | |
JSONDataConstIteratorDetail(nlohmann::json::const_iterator _it) | |
: it(_it) {} | |
}; | |
struct JSONDataDetail | |
{ | |
using Owner = nlohmann::json; | |
using Child = std::reference_wrapper<nlohmann::json>; | |
std::variant<Owner, Child> m_json; | |
JSONDataDetail() = default; | |
JSONDataDetail(const JSONDataDetail&) = default; | |
JSONDataDetail& operator = (JSONDataDetail&&) = default; | |
JSONDataDetail(const nlohmann::json& owner) : m_json(owner) {} | |
JSONDataDetail(nlohmann::json&& owner) : m_json(std::move(owner)) {} | |
JSONDataDetail(nlohmann::json& child) : m_json(child) {} | |
nlohmann::json& get() | |
{ | |
if (m_json.index() == 0) | |
{ | |
return std::get<0>(m_json); | |
} | |
return std::get<1>(m_json).get(); | |
} | |
const nlohmann::json& get() const | |
{ | |
if (m_json.index() == 0) | |
{ | |
return std::get<0>(m_json); | |
} | |
return std::get<1>(m_json).get(); | |
} | |
nlohmann::json* operator ->() | |
{ | |
if (m_json.index() == 0) | |
{ | |
return &std::get<0>(m_json); | |
} | |
return &std::get<1>(m_json).get(); | |
} | |
const nlohmann::json* operator ->() const | |
{ | |
if (m_json.index() == 0) | |
{ | |
return &std::get<0>(m_json); | |
} | |
return &std::get<1>(m_json).get(); | |
} | |
}; | |
} | |
//////////////////////////////// | |
// | |
// JSONDataIterator | |
// | |
JSONDataIterator::JSONDataIterator(const JSONDataIterator& rhs) | |
: m_detail(std::make_shared<detail::JSONDataIteratorDetail>(*rhs.m_detail)) {} | |
JSONDataIterator::JSONDataIterator(const detail::JSONDataIteratorDetail& d) | |
: m_detail(std::make_shared<detail::JSONDataIteratorDetail>(d.it)) {} | |
JSONDataIterator& JSONDataIterator::operator++() | |
{ | |
++m_detail->it; | |
return *this; | |
} | |
JSONDataIterator JSONDataIterator::operator++(int) | |
{ | |
const detail::JSONDataIteratorDetail tmp{ m_detail->it++ }; | |
return JSONDataIterator(tmp); | |
} | |
JSONDataIterator JSONDataIterator::operator+(size_t index) const | |
{ | |
const detail::JSONDataIteratorDetail tmp{ m_detail->it + index }; | |
return JSONDataIterator(tmp); | |
} | |
JSONItem JSONDataIterator::operator *() const | |
{ | |
return { key(), JSONData(detail::JSONDataDetail(*m_detail->it)) }; | |
} | |
String JSONDataIterator::key() const | |
{ | |
return Unicode::FromUTF8(m_detail->it.key()); | |
} | |
JSONData JSONDataIterator::value() const | |
{ | |
return JSONData(detail::JSONDataDetail(m_detail->it.value())); | |
} | |
bool JSONDataIterator::operator ==(const JSONDataIterator& other) const noexcept | |
{ | |
return m_detail->it == other.m_detail->it; | |
} | |
//////////////////////////////// | |
// | |
// JSONDataConstIterator | |
// | |
JSONDataConstIterator::JSONDataConstIterator(const JSONDataConstIterator& rhs) | |
: m_detail(std::make_shared<detail::JSONDataConstIteratorDetail>(*rhs.m_detail)) {} | |
JSONDataConstIterator::JSONDataConstIterator(const detail::JSONDataConstIteratorDetail& d) | |
: m_detail(std::make_shared<detail::JSONDataConstIteratorDetail>(d.it)) {} | |
JSONDataConstIterator& JSONDataConstIterator::operator++() | |
{ | |
++m_detail->it; | |
return *this; | |
} | |
JSONDataConstIterator JSONDataConstIterator::operator++(int) | |
{ | |
const detail::JSONDataConstIteratorDetail tmp{ m_detail->it++ }; | |
return JSONDataConstIterator(tmp); | |
} | |
JSONDataConstIterator JSONDataConstIterator::operator+(size_t index) const | |
{ | |
const detail::JSONDataConstIteratorDetail tmp{ m_detail->it + index }; | |
return JSONDataConstIterator(tmp); | |
} | |
const JSONItem JSONDataConstIterator::operator *() const | |
{ | |
return { key(), JSONData(detail::JSONDataDetail(const_cast<nlohmann::json&>(*m_detail->it))) }; | |
} | |
String JSONDataConstIterator::key() const | |
{ | |
return Unicode::FromUTF8(m_detail->it.key()); | |
} | |
const JSONData JSONDataConstIterator::value() const | |
{ | |
return JSONData(detail::JSONDataDetail(const_cast<nlohmann::json&>(*m_detail->it))); | |
} | |
bool JSONDataConstIterator::operator ==(const JSONDataConstIterator& other) const noexcept | |
{ | |
return m_detail->it == other.m_detail->it; | |
} | |
//////////////////////////////// | |
// | |
// JSONData | |
// | |
Optional<int64> JSONData::getOptInt64() const | |
{ | |
if (!isNumber()) | |
{ | |
return none; | |
} | |
if (isBool()) | |
{ | |
return static_cast<int64>(m_data->get().get<bool>()); | |
} | |
return m_data->get().get<int64_t>(); | |
} | |
Optional<double> JSONData::getOptDouble() const | |
{ | |
if (!isNumber()) | |
{ | |
return none; | |
} | |
return m_data->get().get<double>(); | |
} | |
Optional<String> JSONData::getOptString() const | |
{ | |
if (!isString()) | |
{ | |
return none; | |
} | |
return Optional<String>(InPlace, getString()); | |
} | |
Optional<bool> JSONData::getOptBool() const | |
{ | |
if (!isBool()) { | |
return none; | |
} | |
return m_data->get().get<bool>(); | |
} | |
JSONData::JSONData(const JSONData& data) | |
{ | |
if (data.m_data) | |
{ | |
m_data = std::make_shared<detail::JSONDataDetail>(nlohmann::json(data.m_data->get())); | |
} | |
} | |
JSONData::JSONData(std::nullptr_t) | |
: m_data(std::make_shared<detail::JSONDataDetail>()) {} | |
JSONData::JSONData(const detail::JSONDataDetail& data) | |
: m_data(std::make_shared<detail::JSONDataDetail>(data)) {} | |
JSONData::JSONData(int64 value) | |
: m_data(std::make_shared<detail::JSONDataDetail>(nlohmann::json(value))) {} | |
JSONData::JSONData(uint64 value) | |
: m_data(std::make_shared<detail::JSONDataDetail>(nlohmann::json(value))) {} | |
JSONData::JSONData(double value) | |
: m_data(std::make_shared<detail::JSONDataDetail>(nlohmann::json(value))) {} | |
JSONData::JSONData(bool value) | |
: m_data(std::make_shared<detail::JSONDataDetail>(nlohmann::json(value))) {} | |
JSONData::JSONData(StringView value) | |
: m_data(std::make_shared<detail::JSONDataDetail>(nlohmann::json(Unicode::ToUTF8(value)))) {} | |
JSONData::JSONData(const Array<JSONData>& array) | |
: m_data() | |
{ | |
*this = array; | |
} | |
JSONData::JSONData(const std::initializer_list<std::pair<String, JSONData>>& list) | |
: m_data() | |
{ | |
*this = list; | |
} | |
bool JSONData::isNull() const | |
{ | |
return !isEmpty() && m_data->get().is_null(); | |
} | |
bool JSONData::isBool() const | |
{ | |
return !isEmpty() && m_data->get().is_boolean(); | |
} | |
bool JSONData::isNumber() const | |
{ | |
return !isEmpty() && m_data->get().is_number(); | |
} | |
bool JSONData::isInteger() const | |
{ | |
return !isEmpty() && m_data->get().is_number_integer(); | |
} | |
bool JSONData::isUnsigned() const | |
{ | |
return !isEmpty() && m_data->get().is_number_unsigned(); | |
} | |
bool JSONData::isFloat() const | |
{ | |
return !isEmpty() && m_data->get().is_number_float(); | |
} | |
bool JSONData::isString() const | |
{ | |
return !isEmpty() && m_data->get().is_string(); | |
} | |
bool JSONData::isArray() const | |
{ | |
return !isEmpty() && m_data->get().is_array(); | |
} | |
bool JSONData::isObject() const | |
{ | |
return !isEmpty() && m_data->get().is_object(); | |
} | |
JSONValueType JSONData::getType() const | |
{ | |
if (isEmpty()) | |
{ | |
return JSONValueType::Empty; | |
} | |
else if (isArray()) | |
{ | |
return JSONValueType::Array; | |
} | |
else if (isBool()) | |
{ | |
return JSONValueType::Bool; | |
} | |
else if (isNull()) | |
{ | |
return JSONValueType::Null; | |
} | |
else if (isNumber()) | |
{ | |
return JSONValueType::Number; | |
} | |
else if (isObject()) | |
{ | |
return JSONValueType::Object; | |
} | |
else if (isString()) | |
{ | |
return JSONValueType::String; | |
} | |
throw Error(U"Unknown JSONData"); | |
} | |
bool JSONData::hasMember(StringView name) const | |
{ | |
return !isEmpty() && m_data->get().contains(Unicode::ToUTF8(name)); | |
} | |
String JSONData::getString() const | |
{ | |
if (!isString()) | |
{ | |
return String(); | |
} | |
return Unicode::FromUTF8(m_data->get().get<std::string>()); | |
} | |
JSONData::reference JSONData::operator [](StringView name) | |
{ | |
if (isObject() || isNull()) | |
{ | |
return JSONData(detail::JSONDataDetail(m_data->get()[Unicode::ToUTF8(name)])); | |
} | |
throw Error(U"JSONData::operator []() : Invalid JSON type"); | |
} | |
JSONData::const_reference JSONData::operator [](StringView name) const | |
{ | |
if (!isObject()) | |
{ | |
throw Error(U"JSONData::operator []() : Invalid JSON type"); | |
} | |
auto it = m_data->get().find(Unicode::ToUTF8(name)); | |
if (it != m_data->get().end()) | |
{ | |
return JSONData(detail::JSONDataDetail(const_cast<nlohmann::json&>(it.value()))); | |
} | |
throw Error(U"JSONData::operator []() : The key named \"" + name + U"\" does not exsist."); | |
} | |
JSONData::reference JSONData::operator[](size_t idx) | |
{ | |
if (isArray() || isNull()) | |
{ | |
return JSONData(detail::JSONDataDetail(m_data->get()[idx])); | |
} | |
throw Error(U"JSONData::operator []() : Invalid JSON type"); | |
} | |
JSONData::const_reference JSONData::operator[](size_t idx) const | |
{ | |
if (!isArray()) | |
{ | |
throw Error(U"JSONData::operator []() : Invalid JSON type"); | |
} | |
if (m_data->get().size() <= idx) | |
{ | |
return JSONData(detail::JSONDataDetail(const_cast<nlohmann::json&>(m_data->get()[idx]))); | |
} | |
throw Error(U"JSONData::operator []() : Out of range."); | |
} | |
JSONData::reference JSONData::access(StringView jsonPointer) | |
{ | |
if (jsonPointer.empty() || jsonPointer[0] != U'/') | |
{ | |
throw Error(U"JSONData::access() : Invalid JSON pointer"); | |
} | |
if (isObject() || isArray() || isNull()) | |
{ | |
return JSONData(detail::JSONDataDetail(m_data->get()[nlohmann::json::json_pointer(Unicode::ToUTF8(jsonPointer))])); | |
} | |
throw Error(U"JSONData::access() : Invalid JSON type"); | |
} | |
JSONData::const_reference JSONData::access(StringView jsonPointer) const | |
{ | |
if (jsonPointer.empty() || jsonPointer[0] != U'/') | |
{ | |
throw Error(U"JSONData::access() : Invalid JSON pointer"); | |
} | |
if (!isObject() && !isArray()) | |
{ | |
throw Error(U"JSONData::access() const : Invalid JSON type"); | |
} | |
auto&& pointer = nlohmann::json::json_pointer(Unicode::ToUTF8(jsonPointer)); | |
if (m_data->get().contains(pointer)) | |
{ | |
return JSONData(detail::JSONDataDetail(const_cast<nlohmann::json&>(m_data->get()[pointer]))); | |
} | |
throw Error(U"JSONData::access() : The key specified by \"" + jsonPointer + U"\" does not exsist."); | |
} | |
JSONData::iterator JSONData::begin() | |
{ | |
return iterator(detail::JSONDataIteratorDetail(m_data->get().begin())); | |
} | |
JSONData::const_iterator JSONData::begin() const | |
{ | |
return const_iterator(detail::JSONDataConstIteratorDetail(m_data->get().begin())); | |
} | |
JSONData::iterator JSONData::end() | |
{ | |
return iterator(detail::JSONDataIteratorDetail(m_data->get().end())); | |
} | |
JSONData::const_iterator JSONData::end() const | |
{ | |
return const_iterator(detail::JSONDataConstIteratorDetail(m_data->get().end())); | |
} | |
size_t JSONData::size() const | |
{ | |
if (!isArray()) | |
{ | |
return 0; | |
} | |
return m_data->get().size(); | |
} | |
String JSONData::format(char32 ch, size_t count) const | |
{ | |
if (isEmpty()) | |
{ | |
return String(); | |
} | |
return Unicode::FromUTF8(m_data->get().dump(static_cast<int>(count), static_cast<char>(ch))); | |
} | |
String JSONData::formatMinimum() const | |
{ | |
if (isEmpty()) | |
{ | |
return String(); | |
} | |
return Unicode::FromUTF8(m_data->get().dump()); | |
} | |
bool JSONData::parse(StringView str) | |
{ | |
m_data = std::make_shared<detail::JSONDataDetail>(nlohmann::json::parse(Unicode::ToUTF8(str))); | |
return static_cast<bool>(*this); | |
} | |
bool JSONData::load(FilePathView path) | |
{ | |
TextReader reader(path); | |
if (!reader) | |
{ | |
*this = nullptr; | |
} | |
else | |
{ | |
m_data = std::make_shared<detail::JSONDataDetail>(nlohmann::json::parse(Unicode::ToUTF8(reader.readAll()))); | |
} | |
return static_cast<bool>(*this); | |
} | |
JSONData& JSONData::operator = (int64 value) | |
{ | |
m_data = std::make_shared<detail::JSONDataDetail>(nlohmann::json(value)); | |
return *this; | |
} | |
JSONData& JSONData::operator = (uint64 value) | |
{ | |
m_data = std::make_shared<detail::JSONDataDetail>(nlohmann::json(value)); | |
return *this; | |
} | |
JSONData& JSONData::operator = (double value) | |
{ | |
m_data = std::make_shared<detail::JSONDataDetail>(nlohmann::json(value)); | |
return *this; | |
} | |
JSONData& JSONData::operator = (bool value) | |
{ | |
m_data = std::make_shared<detail::JSONDataDetail>(nlohmann::json(value)); | |
return *this; | |
} | |
JSONData& JSONData::operator = (StringView str) | |
{ | |
m_data = std::make_shared<detail::JSONDataDetail>(nlohmann::json(Unicode::ToUTF8(str))); | |
return *this; | |
} | |
JSONData& JSONData::operator = (const Array<JSONData>& array) | |
{ | |
m_data = std::make_shared<detail::JSONDataDetail>( | |
array.map( | |
[](auto&& data) | |
{ | |
return (data.m_data ? data.m_data->get() : nlohmann::json()); | |
} | |
)); | |
return *this; | |
} | |
JSONData& JSONData::operator = (const std::initializer_list<std::pair<String, JSONData>>& list) | |
{ | |
m_data = std::make_shared<detail::JSONDataDetail>(nlohmann::json::object()); | |
for (auto&& data : list) | |
{ | |
m_data->get()[Unicode::ToUTF8(data.first)] = (data.second.m_data ? data.second.m_data->get() : nlohmann::json()); | |
} | |
return *this; | |
} | |
JSONData LoadJSON(FilePathView path) | |
{ | |
JSONData json; | |
json.load(path); | |
return std::move(json); | |
} | |
//////////////////////////////// | |
// | |
// Format | |
// | |
void Formatter(FormatData& formatData, const JSONData& json) | |
{ | |
if (json) | |
{ | |
Formatter(formatData, json.format()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment