Search code examples
c++jsonnlohmann-json

Write an Eigen Matrix to json file using nlohmann json using to_json method


I have an Eigen matrix defined -

template <typename T>
using Vec3 = Eigen::Matrix<T, 1, 3, Eigen::DontAlign | Eigen::ColMajor>;
using Vec3d = Vec3<double>;

I try to write Vec3d to json file like below -

template <typename T>
void to_json(json& j, const Vec3<T>& v) {
    j = {{"X", v(0)}, {"Y", v(1)}, {"Z", v(2)}};
}

// Usage
Vec3d test(1.f, 2.f, 3.f);
frameJson["Vec3d"] = test;

Output is stored as an array and not like the way specified in to_json, seems like it is not entering the to_json ??

"Vec3d": [
 1.0,
 2.0,
 3.0
]

But I want it like the way specified in to_json like below -

"Vec3d": [
 "X": 1.0,
 "Y": 2.0,
 "Z": 0.0
]

Is something wrong in the way templated to_json is implemented. How do I make this work.

PS : Also how would the templated adl_serializer from_json() look like while reading ?


Solution

  • I failed to find where the default Eigen::Matrix json serializer is implemented, but to have your custom serializer working, just put it inside Eigen namespace:

    namespace Eigen
    {
        template <typename T>
        void to_json(json& j, const Vec3<T>& v) {
        j = {{"X", v(0)}, {"Y", v(1)}, {"Z", v(2)}};
    }
    

    Alternatively, like suggested in the documentation for third-party types serialization, you can write adl_serializer specialization:

    namespace nlohmann {
        template <typename T>
        struct adl_serializer<Vec3<T>> {
            static void to_json(json& j, const Vec3<T>& v) {
                j = {{"X", v(0)}, {"Y", v(1)}, {"Z", v(2)}};
            }
            static void from_json(const json& j, Vec3<T>& v) {
                v(0) = j["X"];
                v(1) = j["Y"];
                v(2) = j["Z"];
            }
        };
    }
    

    Second option might be preferable in general, as it doesn't pollute your third-party namespace.

    Demo