#pragma once ///@file #include #include namespace nix { const nlohmann::json * get(const nlohmann::json & map, const std::string & key); nlohmann::json * get(nlohmann::json & map, const std::string & key); /** * For `adl_serializer>` below, we need to track what * types are not already using `null`. Only for them can we use `null` * to represent `std::nullopt`. */ template struct json_avoids_null; /** * Handle numbers in default impl */ template struct json_avoids_null : std::bool_constant::value> {}; template<> struct json_avoids_null : std::false_type {}; template<> struct json_avoids_null : std::true_type {}; template<> struct json_avoids_null : std::true_type {}; template struct json_avoids_null> : std::true_type {}; template struct json_avoids_null> : std::true_type {}; template struct json_avoids_null> : std::true_type {}; } namespace nlohmann { /** * This "instance" is widely requested, see * https://github.com/nlohmann/json/issues/1749, but momentum has stalled * out. Writing there here in Nix as a stop-gap. * * We need to make sure the underlying type does not use `null` for this to * round trip. We do that with a static assert. */ template struct adl_serializer> { static std::optional from_json(const json & json) { static_assert( nix::json_avoids_null::value, "null is already in use for underlying type's JSON"); return json.is_null() ? std::nullopt : std::optional { adl_serializer::from_json(json) }; } static void to_json(json & json, std::optional t) { static_assert( nix::json_avoids_null::value, "null is already in use for underlying type's JSON"); if (t) adl_serializer::to_json(json, *t); else json = nullptr; } }; }