module discord.w.json;

string stripLastUnderscore(string s) @safe
{
	if (s.length && s[$ - 1] == '_')
		return s[0 .. $ - 1];
	else
		return s;
}

mixin template OptionalSerializer(T)
{
	import std.traits;

	import vibe.data.json;
	import vibe.data.serialization;

	Json toJson() const @safe
	{
		Json ret = Json.emptyObject;
		static foreach (field; FieldNameTuple!T)
		{
			static if (hasUDA!(__traits(getMember, this, field), OptionalAttribute!DefaultPolicy))
			{
				if (__traits(getMember, this, field) != typeof(__traits(getMember, this, field)).init)
				{
					ret[field.stripLastUnderscore] = serializeToJson(__traits(getMember, this, field));
				}
			}
			else
				ret[field.stripLastUnderscore] = serializeToJson(__traits(getMember, this, field));
		}
		return ret;
	}

	static T fromJson(Json src) @safe
	{
		T ret;
		Members: foreach (key, member; src.get!(Json[string]))
		{
			static foreach (field; FieldNameTuple!T)
			{
				if (field.stripLastUnderscore == key)
				{
					if (member.type != Json.Type.null_)
						__traits(getMember, ret, field) = deserializeJson!(typeof(__traits(getMember,
								ret, field)))(member);
					continue Members;
				}
			}
		}
		return ret;
	}
}