20 #ifndef MIO_IO_JSON_SERIALIZER_H
21 #define MIO_IO_JSON_SERIALIZER_H
24 #include <boost/function_types/components.hpp>
25 #include <type_traits>
27 #ifdef MEMILIO_HAS_JSONCPP
33 #include "json/json.h"
52 struct JsonType : std::false_type {
56 struct JsonType<bool> : std::true_type {
57 static IOResult<bool> transform(
const Json::Value& js)
64 static Json::Value transform(
bool b)
74 struct JsonType<T> : std::true_type {
75 static IOResult<T> transform(
const Json::Value& js)
86 static Json::Value transform(T
i)
88 return Json::Value(Json::Int(
i));
94 struct JsonType<T> : std::true_type {
95 static IOResult<T> transform(
const Json::Value& js)
98 unsigned int i = js.asUInt();
103 "Json value is not in range of the requested unsigned integer type.");
107 static Json::Value transform(T
i)
109 return Json::Value(Json::UInt(
i));
115 struct JsonType<T> : std::true_type {
116 static IOResult<T> transform(
const Json::Value& js)
123 static Json::Value transform(T
i)
125 return {Json::Int64(
i)};
131 struct JsonType<T> : std::true_type {
132 static IOResult<T> transform(
const Json::Value& js)
139 static Json::Value transform(T
i)
141 return {Json::UInt64(
i)};
146 struct JsonType<double> : std::true_type {
148 static IOResult<double> transform(
const Json::Value& js)
155 static Json::Value transform(
double d)
162 struct JsonType<float> : std::true_type {
163 static IOResult<float> transform(
const Json::Value& js)
166 auto d = js.asDouble();
174 static Json::Value transform(
float f)
181 struct JsonType<
std::string> : std::true_type {
182 static IOResult<std::string> transform(
const Json::Value& js)
189 static Json::Value transform(
const std::string& s)
196 struct JsonType<const char*> : std::true_type {
198 static Json::Value transform(
const char* s)
212 class JsonObject :
public SerializerBase
221 JsonObject(Json::Value&
value,
const std::shared_ptr<IOStatus>& status,
int flags)
222 : SerializerBase{status, flags}
236 void add_element(
const std::string& name,
const T&
value);
239 void add_element(
const std::string& name,
const T&
value);
249 void add_optional(
const std::string& name,
const T*
value);
258 template <
class Iter>
259 void add_list(
const std::string& name, Iter b, Iter e);
271 IOResult<T> expect_element(
const std::string& name, Tag<T> tag)
const;
274 IOResult<T> expect_element(
const std::string& name, Tag<T> tag)
const;
286 IOResult<boost::optional<T>> expect_optional(
const std::string& name,
mio::Tag<T> tag);
296 IOResult<std::vector<T>> expect_list(
const std::string& name, Tag<T> tag);
301 const auto&
value() const&
307 Json::Value& m_value;
313 class JsonContext :
public SerializerBase
322 JsonContext(
const std::shared_ptr<IOStatus>& status,
int flags)
323 : SerializerBase{status, flags}
335 JsonContext(Json::Value
value,
const std::shared_ptr<IOStatus>& status,
int flags)
336 : SerializerBase(status, flags)
348 JsonObject create_object(
const std::string& type)
351 m_value = Json::Value(Json::objectValue);
352 return {m_value, m_status, m_flags};
362 JsonObject expect_object(
const std::string& type)
365 if (!m_value.isObject()) {
368 return {m_value, m_status, m_flags};
375 const Json::Value&
value() const&
382 Json::Value&&
value() &&
384 return std::move(m_value);
399 io.m_value = JsonType<T>::transform(t);
413 return JsonType<T>::transform(io.m_value);
420 template <IsContainer Container>
421 requires(!IsJsonType<Container> && !HasDeserialize<Container, JsonContext>)
424 if (io.m_status->is_ok()) {
425 auto array = Json::Value(Json::arrayValue);
428 for (
auto it =
begin(v); it !=
end(v); ++it) {
429 auto ctxt = JsonContext(io.m_status, io.m_flags);
432 array.append(std::move(ctxt).
value());
435 io.m_value = std::move(array);
443 template <IsContainer Container>
444 requires(!IsJsonType<Container> && !HasDeserialize<Container, JsonContext>)
447 const auto& array = io.m_value;
448 if (array.isArray()) {
450 for (
auto&& el : array) {
451 auto ctxt = JsonContext(el, io.m_status, io.m_flags);
452 BOOST_OUTCOME_TRY(
auto&& val,
mio::deserialize(ctxt, Tag<typename Container::value_type>{}));
453 v.insert(v.end(), val);
470 inline IOResult<void> write_json(
const std::string& path,
const Json::Value& js_value)
472 std::ofstream ofs(path);
474 Json::StreamWriterBuilder swb;
475 auto js_writer = std::unique_ptr<Json::StreamWriter>(swb.newStreamWriter());
476 js_writer->write(js_value, &ofs);
497 IOResult<Json::Value> serialize_json(
const T& t,
int flags =
IOF_None)
499 JsonContext ctxt{std::make_shared<IOStatus>(), flags};
501 if (!ctxt.status()) {
516 IOResult<void> write_json(
const std::string& path,
const T& t,
int flags =
IOF_None)
518 BOOST_OUTCOME_TRY(
auto&& js, serialize_json(t, flags));
519 return write_json(path, js);
527 inline IOResult<Json::Value> read_json(
const std::string& path)
529 std::ifstream ifs(path);
531 Json::CharReaderBuilder crb;
533 Json::Value js_value;
534 if (Json::parseFromStream(crb, ifs, &js_value, &err_msg)) {
551 IOResult<T> deserialize_json(
const Json::Value& js, Tag<T> tag,
int flags =
IOF_None)
553 JsonContext ctxt{js, std::make_shared<IOStatus>(), flags};
554 return deserialize(
static_cast<JsonContext&
>(ctxt), tag);
566 IOResult<T> read_json(
const std::string& path, Tag<T> tag,
int flags =
IOF_None)
568 BOOST_OUTCOME_TRY(
auto&& js, read_json(path));
569 return deserialize_json(js, tag, flags);
578 void JsonObject::add_element(
const std::string& name,
const T&
value)
580 if (m_status->is_ok()) {
581 m_value[name] = JsonType<T>::transform(
value);
587 void JsonObject::add_element(
const std::string& name,
const T&
value)
589 if (m_status->is_ok()) {
590 auto ctxt = JsonContext(m_status, m_flags);
593 m_value[name] = std::move(ctxt).value();
599 void JsonObject::add_optional(
const std::string& name,
const T*
value)
602 add_element(name, *
value);
606 template <
class Iter>
609 if (m_status->is_ok()) {
610 auto array = Json::Value(Json::arrayValue);
611 for (
auto it = b; it != e; ++it) {
612 auto ctxt = JsonContext(m_status, m_flags);
615 array.append(std::move(ctxt).
value());
618 m_value[name] = std::move(array);
624 IOResult<T> JsonObject::expect_element(
const std::string& name, Tag<T> )
const
626 if (m_status->is_error()) {
630 const auto& element = m_value[name];
631 if (element.isNull()) {
634 auto r = JsonType<T>::transform(element);
639 return failure(r.error().code(),
640 r.error().message() +
" (" + name +
")");
645 IOResult<T> JsonObject::expect_element(
const std::string& name, Tag<T> tag)
const
647 if (m_status->is_error()) {
650 const auto& element = m_value[name];
651 if (!element.isNull()) {
652 auto ctxt = JsonContext(element, m_status, m_flags);
660 IOResult<boost::optional<T>> JsonObject::expect_optional(
const std::string& name,
mio::Tag<T> tag)
662 if (m_status->is_error()) {
665 const auto& element = m_value[name];
666 if (element.isNull()) {
667 return success(boost::optional<T>{});
669 auto r = expect_element(name, tag);
677 IOResult<std::vector<T>> JsonObject::expect_list(
const std::string& name, Tag<T> tag)
679 if (m_status->is_error()) {
682 const auto& array = m_value[name];
683 if (array.isArray()) {
685 v.reserve(array.size());
686 for (
auto&& el : array) {
687 auto ctxt = JsonContext(el, m_status, m_flags);
690 v.emplace_back(r.value());
static min_max_return_type< ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 >, ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > >::type min(const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &a, const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &b)
Definition: ad.hpp:2599
static min_max_return_type< ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 >, ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > >::type max(const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &a, const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &b)
Definition: ad.hpp:2596
trait_value< T >::RETURN_TYPE & value(T &x)
Definition: ad.hpp:3308
A collection of classes to simplify handling of matrix shapes in meta programming.
Definition: models/abm/analyze_result.h:30
Tag< Container >
Definition: io.h:807
requires details::IsElementReference< M > RowMajorIterator< M, false > end(M &m)
create a non-const end iterator for the matrix m.
Definition: eigen_util.h:449
IOResult< T > deserialize(IOContext &io, Tag< T > tag)
Restores an object from the data stored in an IO context.
Definition: io.h:860
auto failure(const IOStatus &s)
Create an object that is implicitly convertible to an error IOResult<T>.
Definition: io.h:380
void serialize(IOContext &io, const T &t)
Save data that describes an object in a format determined by the given context.
Definition: io.h:836
boost::outcome_v2::in_place_type_t< T > Tag
Type that is used for overload resolution.
Definition: io.h:407
auto i
Definition: io.h:809
requires(!std::is_trivial_v< T >) void BinarySerializerObject
Definition: binary_serializer.h:333
auto success()
Create an object that is implicitly convertible to a succesful IOResult<void>.
Definition: io.h:359
void unused(T &&...)
Does nothing, can be used to mark variables as not used.
Definition: compiler_diagnostics.h:30
requires details::IsElementReference< M > RowMajorIterator< M, false > begin(M &m)
create a non-const iterator to first element of the matrix m.
Definition: eigen_util.h:421
obj add_list("Items", container.begin(), container.end())
@ IOF_None
default behavior.
Definition: io.h:70
IOResult< T > deserialize_internal(IOContext &io, Tag< T > tag)
Deserialization implementation for the default serialization feature.
Definition: default_serialize.h:236
void serialize_internal(IOContext &io, const T &a)
Serialization implementation for the default serialization feature.
Definition: default_serialize.h:213