// // jsonizer.h // serializer // // Created by Sam Jaffe on 3/15/23. // #pragma once #include #include #include #include #include #include namespace serializer { class Jsonizer { public: template Json::Value to_json(T const & value) const; template void from_json(T & value, Json::Value const & json) const; template T from_json(Json::Value const & json) const; /** * @brief Load an object from either JSON, or from p_cache, depending on * the structure of the inputs. * @param ptr A pointer to an uninstantiated value * @param json A JSON object or string. If json is a string, then we attempt * to load ptr from p_cache, according to {@see Json::Value::asString}. If * json is an object, then we instead construct it like normal and attempt * to store the new object in p_cache. * @throws If json.isString() and T is not a recognized type in shared_cache * then this function will throw according to {@see shared_cache::fetch}. */ template void from_json(std::shared_ptr & ptr, Json::Value const & json) const; template Json::Value to_json(std::optional const & opt) const; template void from_json(std::optional & opt, Json::Value const & json) const; /** * @brief Construct an object of type 'T' from a datastream * @tparam T the output type to be deserialized * @param in A stream of JSON data * @return A newly constructed object by value */ template T from_stream(std::istream & in) const; template T from_string(std::string_view in) const; /** * @brief Write an object out to a datastream, such as std::cout or a file * @tparam T the input type to be serialized * @param value The instance of type T to serialize * @param out an output stream of any sort */ template void to_stream(T const & value, std::ostream & out) const; /** * @brief Construct an object of type 'T' from a file handle * @tparam T the output type to be deserialized * @param file the name of a JSON file on disk to be read * @return A newly constructed object by value */ template T from_file(std::string const & file) const; /** * @brief Construct a jsonizer with a personal instance of the data cache. * Because there is no getter for p_cache, all cached instances are locally * stored, meaning that each jsonizer default-constructed will have a * different state of the cache. */ Jsonizer(); /** * @brief Construct a jsonizer with an externally owned cache * @param cache A shared_ptr to a data cache. Cannot be null * @throws std::logic_error if cache == nullptr */ Jsonizer(std::shared_ptr cache); /** * Do not permit the construction of a jsonizer from a nullptr literal. * This moves the run-time exception std::logic_error to compiler time. */ Jsonizer(std::nullptr_t) = delete; private: template Json::Value to_json(T & value, std::index_sequence) const; template void from_json(T & value, Json::Value const & json, std::index_sequence) const; template Json::Value to_json_impl(T const & value) const; template void from_json_impl(T & value, Json::Value const & json) const; template T from_cached_json(std::string const & key, Json::Value const & json, F && fetch) const; private: std::shared_ptr p_cache; }; }