Search code examples
c++nlohmann-json

How to serialize/deserialize custom class templates with nlohmann::json


For some reason I get conversion errors with this code:

template<typename T>
class MyType {
    T data;
};

template<typename T>
void from_json(MyType<T>& t, const nlohmann::json& j) {}

template<typename T>
void to_json(const MyType<T>& t, nlohmann::json& j) {}

int main() {
    MyType<std::string> f;
    nlohmann::json j = f; //error
    f = j.template get<MyType<std::string>>(); //error
}

I'm writing a library type that uses nlohmann::json and I would not like the user to have to write boilerplate serialization for every template instantiation. Is there a way to do this? If not, why exactly is the compiler complaining?


Solution

  • You have got the parameters of from_json and to_json inverted. The signatures of from_json and to_json are:

    template<typename ValueType>
    struct adl_serializer {
        template<typename BasicJsonType>
        static void to_json(BasicJsonType& j, const T& value) {
            // calls the "to_json" method in T's namespace
        }
    
        template<typename BasicJsonType>
        static void from_json(const BasicJsonType& j, T& value) {
            // same thing, but with the "from_json" method
        }
    };
    

    Therefore, you should list Json as the first parameter. Once you do that, the code compiles successfully.

    Fixed code:

    template<typename T>
    class MyType {
        T data;
    };
    
    template<typename T>
    void from_json(const nlohmann::json& j, MyType<T>& t) {}
    
    template<typename T>
    void to_json(nlohmann::json& j, const MyType<T>& t) {}
    
    int main() {
        MyType<std::string> f;
        nlohmann::json j = f;
        f = j.template get<MyType<std::string>>();
    }
    

    Demo: https://godbolt.org/z/fsev5snd6