Skip to content

adl_serializer and CRTP #680

Description

@stevefan1999-personal

Because I really hate defining to_json/from_json by using the infamous ADL trick (I come from a C#/Java background so the fame of ADL depends), I decided to make the OOP-way-of-serialization shim of my own

I was having some progress, the following code demonstrated is a complete valid and legit code:

IJsonSerializable.hpp:

template<class T>
struct IJsonSerializable {
	using self_t = IJsonSerializable<T>;

	constexpr void to_json(json &j) const {
		auto self = const_cast<self_t *>(this);
		static_cast<T *>(self)->to_json(j);
	}

	constexpr void from_json(json &j) const {
		auto self = const_cast<self_t *>(this);
		static_cast<T *>(self)->from_json(j);
	}
};

template <class T>
constexpr void to_json(json &j, const IJsonSerializable<T> *value) {
	value->to_json(j);
}

template <class T>
constexpr void from_json(const json &j, IJsonSerializable<T> *value) {
	auto _j = const_cast<json &>(j);
	value->from_json(_j);
}

template <class T>
constexpr void to_json(json &j, const IJsonSerializable<T> &value) {
	value.to_json(j);
}

template <class T>
constexpr void from_json(const json &j, IJsonSerializable<T> &value) {
	auto _j = const_cast<json &>(j);
	value.from_json(_j);
}

Vector3.hpp:

#include "IJsonSerializable.h"

struct Vector3 : public IJsonSerializable<Vector3> {
	float x, y, z;

public:
	void to_json(json &j)  {
		j = { 
			{ "x", x }, 
			{ "y", y }, 
			{ "z", z} 
		};
	}

	void from_json(json &j) {
		x = j["x"];
		y = j["y"];
		z = j["z"];
	}
};

This works pretty much fine for me, but is there any way to rewrite it in the following form?

namespace nlohmann {
	template <class T>
	struct adl_serializer<IJsonSerializable<T>> { // not working, should I insert SFINAE here?
		using self_t = IJsonSerializable<T>;

		constexpr void to_json(json &j, const self_t *value) {
			value->to_json(j);
		}

		constexpr void from_json(const json &j, self_t *value) {
			auto _j = const_cast<json &>(j);
			value->from_json(_j);
		}

		constexpr void to_json(json &j, const self_t &value) {
			value.to_json(j);
		}

		constexpr void from_json(const json &j, self_t &value) {
			auto _j = const_cast<json &>(j);
			value.from_json(_j);
		}
	};
}

I group all my other serializers into namespace nlohmann just to keep it away from polluting my global namespace without creating another namespace of my own.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    solution: proposed fixa fix for the issue has been proposed and waits for confirmation

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions