34 #include <nlohmann/json.hpp>
36 #include <sol/state_view.hpp>
37 #include <sol/object.hpp>
38 #include <sol/optional.hpp>
39 #include <sol/table.hpp>
40 #include <sol/version.hpp>
42 #if SOL_IS_OFF(SOL_SAFE_NUMERICS) && SOL_IS_OFF(SOL_ALL_SAFETIES_ON)
43 #error "nlohmann support for sol requires at least SOL_SAFE_NUMERICS=1"
44 #include <force_compiler_to_stop_here>
61 struct adl_serializer<sol::object> {
63 static void to_json_array(json& j,
const sol::table& tbl) {
64 if (j.type() != json::value_t::array) {
67 auto kv_args = json::object();
68 for (
auto& kv : tbl) {
69 if (kv.first.get_type() != sol::type::number) {
70 auto key = kv.first.as<std::string>();
71 to_json(kv_args[key], kv.second.as<sol::object>());
74 j.emplace_back(kv.second.as<sol::object>());
76 if (!kv_args.empty()) {
77 j.emplace_back(std::move(kv_args));
82 static void to_json_object(json& j,
const sol::table& tbl) {
83 if (j.type() != json::value_t::object) {
86 for (
auto& kv : tbl) {
87 auto key = kv.first.as<std::string>();
88 to_json(j[key], kv.second.as<sol::object>());
93 static void to_json(json& j,
const sol::table& tbl) {
94 if (tbl.pairs().begin() == tbl.pairs().end()) {
97 if (j.type() == json::value_t::null) {
106 auto first = (*tbl.pairs().begin()).first;
107 bool looks_like_array = (first.get_type() == sol::type::number);
108 if (looks_like_array) {
109 to_json_array(j, tbl);
111 to_json_object(j, tbl);
116 static void to_json(json& j,
const sol::object& obj) {
117 switch (obj.get_type()) {
118 case sol::type::table: {
119 to_json(j, obj.as<sol::table>());
122 case sol::type::string: {
123 j = obj.as<std::string>();
126 case sol::type::boolean: {
130 case sol::type::number: {
133 if (
auto num = obj.as<sol::optional<int64_t>>(); num) {
136 j = obj.as<
double>();
141 case sol::type::none: {
145 case sol::type::poly:
149 case sol::type::function:
153 case sol::type::thread:
157 case sol::type::userdata:
158 case sol::type::lightuserdata:
165 static void from_json(
const json& j, sol::object& obj) {
166 auto* L = obj.lua_state();
168 throw std::logic_error(
"can only deserialize to existing sol::object");
170 auto lua = sol::state_view(L);
172 case json::value_t::object: {
173 auto tbl = lua.create_table();
174 for (
const auto& it : j.items()) {
175 auto tmp = sol::object(L, sol::in_place,
nullptr);
176 from_json(it.value(), tmp);
182 case json::value_t::null: {
183 obj = sol::object(L, sol::in_place,
nullptr);
186 case json::value_t::array: {
187 auto tbl = lua.create_table();
188 for (
const auto& el : j) {
189 auto tmp = sol::object(L, sol::in_place,
nullptr);
196 case json::value_t::binary: {
197 obj = sol::object(L, sol::in_place,
nullptr);
200 case json::value_t::string: {
201 obj = sol::object(L, sol::in_place, j.get<std::string>());
204 case json::value_t::boolean: {
205 obj = sol::object(L, sol::in_place, j.get<
bool>());
208 case json::value_t::number_float: {
209 obj = sol::object(L, sol::in_place, j.get<
double>());
212 case json::value_t::number_unsigned: {
213 obj = sol::object(L, sol::in_place, j.get<
unsigned long>());
216 case json::value_t::number_integer: {
217 obj = sol::object(L, sol::in_place, j.get<
signed long>());
220 case json::value_t::discarded: {
221 obj = sol::object(L, sol::in_place,
nullptr);
232 inline sol::object into_sol_object(sol::state_view& lua,
const nlohmann::json& json) {
233 auto tmp = sol::object(lua, sol::in_place,
nullptr);
234 nlohmann::adl_serializer<sol::object>::from_json(json, tmp);
238 inline sol::object into_sol_object(sol::this_state& state,
const nlohmann::json& json) {
239 auto lua = sol::state_view(state);
240 auto tmp = sol::object(lua, sol::in_place,
nullptr);
241 nlohmann::adl_serializer<sol::object>::from_json(json, tmp);