chore: change std optional json serialization to not include property if unset

This commit is contained in:
Jan 2024-04-01 14:58:57 +02:00
parent f8c9e62624
commit a2d649ed66
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C
5 changed files with 122 additions and 100 deletions

View File

@ -2,7 +2,7 @@
#include "Game/T6/T6.h" #include "Game/T6/T6.h"
#include "Json/JsonOptional.h" #include "Json/JsonExtension.h"
#include <memory> #include <memory>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <optional> #include <optional>
@ -44,7 +44,7 @@ namespace T6
GfxStencilFunc func; GfxStencilFunc func;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonStencil, pass, fail, zfail, func); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonStencil, pass, fail, zfail, func);
enum class JsonAlphaTest enum class JsonAlphaTest
{ {
@ -154,24 +154,24 @@ namespace T6
std::optional<JsonStencil> stencilBack; std::optional<JsonStencil> stencilBack;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonStateBitsTableEntry, NLOHMANN_DEFINE_TYPE_EXTENSION(JsonStateBitsTableEntry,
srcBlendRgb, srcBlendRgb,
dstBlendRgb, dstBlendRgb,
blendOpRgb, blendOpRgb,
alphaTest, alphaTest,
cullFace, cullFace,
srcBlendAlpha, srcBlendAlpha,
dstBlendAlpha, dstBlendAlpha,
blendOpAlpha, blendOpAlpha,
colorWriteRgb, colorWriteRgb,
colorWriteAlpha, colorWriteAlpha,
polymodeLine, polymodeLine,
depthWrite, depthWrite,
depthWrite, depthWrite,
depthTest, depthTest,
polygonOffset, polygonOffset,
stencilFront, stencilFront,
stencilBack); stencilBack);
class JsonConstant class JsonConstant
{ {
@ -186,12 +186,12 @@ namespace T6
{ {
if (in.name.has_value()) if (in.name.has_value())
{ {
out["name"] = in.name; optional_to_json(out, "name", in.name);
} }
else else
{ {
out["nameFragment"] = in.nameFragment; optional_to_json(out, "nameFragment", in.nameFragment);
out["nameHash"] = in.nameHash; optional_to_json(out, "nameHash", in.nameHash);
} }
out["literal"] = in.literal; out["literal"] = in.literal;
@ -199,9 +199,9 @@ namespace T6
inline void from_json(const nlohmann::json& in, JsonConstant& out) inline void from_json(const nlohmann::json& in, JsonConstant& out)
{ {
in.value("name", nlohmann::json()).get_to(out.name); optional_from_json(in, "name", out.name);
in.value("nameFragment", nlohmann::json()).get_to(out.nameFragment); optional_from_json(in, "nameFragment", out.nameFragment);
in.value("nameHash", nlohmann::json()).get_to(out.nameHash); optional_from_json(in, "nameHash", out.nameHash);
in.at("literal").get_to(out.literal); in.at("literal").get_to(out.literal);
}; };
@ -232,7 +232,7 @@ namespace T6
bool clampW; bool clampW;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonSamplerState, filter, mipMap, clampU, clampV, clampW); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonSamplerState, filter, mipMap, clampU, clampV, clampW);
NLOHMANN_JSON_SERIALIZE_ENUM(TextureSemantic, NLOHMANN_JSON_SERIALIZE_ENUM(TextureSemantic,
{ {
@ -284,13 +284,13 @@ namespace T6
{ {
if (in.name.has_value()) if (in.name.has_value())
{ {
out["name"] = in.name; optional_to_json(out, "name", in.name);
} }
else else
{ {
out["nameHash"] = in.nameHash; optional_to_json(out, "nameHash", in.nameHash);
out["nameStart"] = in.nameStart; optional_to_json(out, "nameStart", in.nameStart);
out["nameEnd"] = in.nameEnd; optional_to_json(out, "nameEnd", in.nameEnd);
} }
out["semantic"] = in.semantic; out["semantic"] = in.semantic;
@ -301,10 +301,10 @@ namespace T6
inline void from_json(const nlohmann::json& in, JsonTexture& out) inline void from_json(const nlohmann::json& in, JsonTexture& out)
{ {
in.value("name", nlohmann::json()).get_to(out.name); optional_from_json(in, "name", out.name);
in.value("nameHash", nlohmann::json()).get_to(out.nameHash); optional_from_json(in, "nameHash", out.nameHash);
in.value("nameStart", nlohmann::json()).get_to(out.nameStart); optional_from_json(in, "nameStart", out.nameStart);
in.value("nameEnd", nlohmann::json()).get_to(out.nameEnd); optional_from_json(in, "nameEnd", out.nameEnd);
in.at("semantic").get_to(out.semantic); in.at("semantic").get_to(out.semantic);
in.at("isMatureContent").get_to(out.isMatureContent); in.at("isMatureContent").get_to(out.isMatureContent);
in.at("samplerState").get_to(out.samplerState); in.at("samplerState").get_to(out.samplerState);
@ -318,7 +318,7 @@ namespace T6
uint8_t columns; uint8_t columns;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonTextureAtlas, rows, columns); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonTextureAtlas, rows, columns);
NLOHMANN_JSON_SERIALIZE_ENUM(MaterialGameFlags, NLOHMANN_JSON_SERIALIZE_ENUM(MaterialGameFlags,
{ {
@ -376,22 +376,22 @@ namespace T6
std::optional<std::string> thermalMaterial; std::optional<std::string> thermalMaterial;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonMaterial, NLOHMANN_DEFINE_TYPE_EXTENSION(JsonMaterial,
gameFlags, gameFlags,
sortKey, sortKey,
textureAtlas, textureAtlas,
surfaceTypeBits, surfaceTypeBits,
layeredSurfaceTypes, layeredSurfaceTypes,
hashIndex, hashIndex,
surfaceFlags, surfaceFlags,
contents, contents,
stateBitsEntry, stateBitsEntry,
stateFlags, stateFlags,
cameraRegion, cameraRegion,
probeMipBits, probeMipBits,
techniqueSet, techniqueSet,
textures, textures,
constants, constants,
stateBits, stateBits,
thermalMaterial); thermalMaterial);
} // namespace T6 } // namespace T6

View File

@ -3,7 +3,7 @@
#include "Game/T6/T6.h" #include "Game/T6/T6.h"
#include "Json/JsonCommon.h" #include "Json/JsonCommon.h"
#include "Json/JsonOptional.h" #include "Json/JsonExtension.h"
#include <memory> #include <memory>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <optional> #include <optional>
@ -21,7 +21,7 @@ namespace T6
float patternScale; float patternScale;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonWeaponCamoSet, solidCamoImage, patternCamoImage, patternOffset, patternScale); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonWeaponCamoSet, solidCamoImage, patternCamoImage, patternOffset, patternScale);
class JsonWeaponCamoMaterialOverride class JsonWeaponCamoMaterialOverride
{ {
@ -30,7 +30,7 @@ namespace T6
std::string camoMaterial; std::string camoMaterial;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonWeaponCamoMaterialOverride, baseMaterial, camoMaterial); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonWeaponCamoMaterialOverride, baseMaterial, camoMaterial);
constexpr auto SHADER_CONST_COUNT = 8; constexpr auto SHADER_CONST_COUNT = 8;
@ -46,7 +46,7 @@ namespace T6
static_assert(SHADER_CONST_COUNT == std::extent_v<decltype(WeaponCamoMaterial::shaderConsts)>); static_assert(SHADER_CONST_COUNT == std::extent_v<decltype(WeaponCamoMaterial::shaderConsts)>);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonWeaponCamoMaterial, useColorMap, useNormalMap, useSpecularMap, materialOverrides, shaderConsts); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonWeaponCamoMaterial, useColorMap, useNormalMap, useSpecularMap, materialOverrides, shaderConsts);
class JsonWeaponCamoMaterialSet class JsonWeaponCamoMaterialSet
{ {
@ -54,7 +54,7 @@ namespace T6
std::vector<JsonWeaponCamoMaterial> materials; std::vector<JsonWeaponCamoMaterial> materials;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonWeaponCamoMaterialSet, materials); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonWeaponCamoMaterialSet, materials);
class JsonWeaponCamo class JsonWeaponCamo
{ {
@ -65,5 +65,5 @@ namespace T6
std::vector<JsonWeaponCamoMaterialSet> camoMaterials; std::vector<JsonWeaponCamoMaterialSet> camoMaterials;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonWeaponCamo, solidBaseImage, patternBaseImage, camoSets, camoMaterials); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonWeaponCamo, solidBaseImage, patternBaseImage, camoSets, camoMaterials);
} // namespace T6 } // namespace T6

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "Json/JsonExtension.h"
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
class JsonVec2 class JsonVec2
@ -9,7 +10,7 @@ public:
float y; float y;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonVec2, x, y); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonVec2, x, y);
class JsonVec3 class JsonVec3
{ {
@ -19,7 +20,7 @@ public:
float z; float z;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonVec3, x, y, z); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonVec3, x, y, z);
class JsonVec4 class JsonVec4
{ {
@ -30,4 +31,4 @@ public:
float w; float w;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(JsonVec4, x, y, z, w); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonVec4, x, y, z, w);

View File

@ -0,0 +1,58 @@
#pragma once
// Credits to
// https://www.kdab.com/jsonify-with-nlohmann-json/
#include <nlohmann/json.hpp>
#include <optional>
// partial specialization (full specialization works too)
namespace nlohmann
{
template<class T> void optional_to_json(nlohmann::json& j, const char* name, const std::optional<T>& value)
{
if (value)
j[name] = *value;
}
template<class T> void optional_from_json(const nlohmann::json& j, const char* name, std::optional<T>& value)
{
const auto it = j.find(name);
if (it != j.end())
value = it->get<T>();
else
value = std::nullopt;
}
template<typename> constexpr bool is_optional = false;
template<typename T> constexpr bool is_optional<std::optional<T>> = true;
template<typename T> void extended_to_json(const char* key, nlohmann::json& j, const T& value)
{
if constexpr (is_optional<T>)
nlohmann::optional_to_json(j, key, value);
else
j[key] = value;
}
template<typename T> void extended_from_json(const char* key, const nlohmann::json& j, T& value)
{
if constexpr (is_optional<T>)
nlohmann::optional_from_json(j, key, value);
else
j.at(key).get_to(value);
}
} // namespace nlohmann
#define EXTEND_JSON_TO(v1) extended_to_json(#v1, nlohmann_json_j, nlohmann_json_t.v1);
#define EXTEND_JSON_FROM(v1) extended_from_json(#v1, nlohmann_json_j, nlohmann_json_t.v1);
#define NLOHMANN_DEFINE_TYPE_EXTENSION(Type, ...) \
inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) \
{ \
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_TO, __VA_ARGS__)) \
} \
inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) \
{ \
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_FROM, __VA_ARGS__)) \
}

View File

@ -1,37 +0,0 @@
#pragma once
#include <nlohmann/json.hpp>
#include <optional>
// partial specialization (full specialization works too)
namespace nlohmann
{
template<typename T> struct adl_serializer<std::optional<T>>
{
static void to_json(json& j, const std::optional<T>& opt)
{
if (!opt.has_value())
{
j = nullptr;
}
else
{
j = *opt; // this will call adl_serializer<T>::to_json which will
// find the free function to_json in T's namespace!
}
}
static void from_json(const json& j, std::optional<T>& opt)
{
if (j.is_null())
{
opt = std::nullopt;
}
else
{
opt = j.template get<T>(); // same as above, but with
// adl_serializer<T>::from_json
}
}
};
} // namespace nlohmann