How to serialize/deserialize an Eigen matrix? #541
-
| I tried using the following code, but it failed. How can I properly serialize an Eigen::Matrix<T, rows, cols>? namespace jsoncons {
template <typename Json, typename T3, int T2, int T1>
struct json_type_traits<Json, Eigen::Matrix<T3, T2, T1>> {
  using allocator_type = Json::allocator_type;
  static bool is(const Json& j) noexcept { return j.is_array(); }
  static Eigen::Matrix<T3, T2, T1> as(const Json& j) {
    if constexpr (T1 == 1) {
      Eigen::Matrix<T3, T2, T1> val(j.template as<std::vector<T3>>().data());
      return val;
    } else {
      Eigen::Matrix<T3, T2, T1> val;
      std::vector<std::vector<T3>> vec = j.template as<std::vector<std::vector<T3>>>();
      for (int i = 0; i < 4; ++i) {
        for (int ii = 0; ii < 5; ++ii) {
          val(i, ii) = vec[i][ii];
        }
      }
      return val;
    }
  }
  static Json to_json(const Eigen::Matrix<T3, T2, T1>& val,
                      allocator_type allocator = allocator_type()) {
    Json j(allocator);
    if constexpr (T1 == 1) {
      for (int i = 0; i < T2; ++i) {
        j.push_back(val(i));
      }
    } else {
      for (int i = 0; i < T2; ++i) {
        Json ji(allocator);
        for (int ii = 0; ii < T1; ++ii) {
          ji.push_back(val(i, ii));
        }
        j.push_back(ji);
      }
    }
    return j;
  }
};
}  // namespace jsoncons
namespace jsoncons {
template <typename T3, int T2, int T1>
struct is_json_type_traits_declared<Eigen::Matrix<T3, T2, T1>>
    : public std::true_type {};
}  // namespace jsoncons | 
Beta Was this translation helpful? Give feedback.
      
      
          Answered by
          
            danielaparker
          
      
      
        Oct 15, 2024 
      
    
    Replies: 1 comment 1 reply
-
| Apologies, just got to this. I would suggest defining separate  namespace jsoncons {
template <typename Json, typename Scalar, std::size_t RowsAtCompileTime, std::size_t ColsAtCompileTime>
struct json_type_traits<Json, Eigen::Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime>>
{
    using allocator_type = typename Json::allocator_type;    
    using matrix_type = Eigen::Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime>;
    
    static bool is(const Json& val) noexcept
    {
        if (!val.is_array() || val.size() != RowsAtCompileTime)
            return false;
        for (std::size_t i = 0; i < val.size(); ++i)
        {
            const Json& row = val[i];
            if (row.size() != ColsAtCompileTime)
            {
                return false;
            }
        }
        return true;
    }
    static matrix_type as(const Json& val)
    {
        if (!val.is_array() || val.size() != RowsAtCompileTime || val[0].size() != ColsAtCompileTime)
        {
            return matrix_type{};
        }
        matrix_type m(RowsAtCompileTime, ColsAtCompileTime);
        
        for (std::size_t i = 0; i < val.size(); ++i)
        {
            const Json& row = val[i];
            if (row.size() != ColsAtCompileTime)
            {
                return matrix_type{};
            }
            for (std::size_t j = 0; j < row.size(); ++j)
            {
                m(i,j) = row[j].as<Scalar>();
            }
        }
        
        return m;
    }
    static Json to_json(const matrix_type& m, const allocator_type& alloc = allocator_type{})
    {
        Json val{ jsoncons::json_array_arg, alloc };
        for (Eigen::Index i = 0; i < m.rows(); ++i)
        {
            Json row{ jsoncons::json_array_arg };
            for (Eigen::Index j = 0; j < m.cols(); ++j)
            {
                row.push_back(m(i, j));
            }
            val.push_back(std::move(row));
        }
        return val;
    }
};
template <typename Json, typename Scalar>
struct json_type_traits<Json, Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>>
{
    using allocator_type = typename Json::allocator_type;    
    using matrix_type = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>;
    
    static bool is(const Json& val) noexcept
    {
        if (!val.is_array())
            return false;
        std::size_t cols = val[0].size();
        for (std::size_t i = 0; i < val.size(); ++i)
        {
            const Json& row = val[i];
            if (row.size() != cols)
            {
                return false;
            }
        }
        return true;
    }
    static matrix_type as(const Json& val)
    {
        if (!val.is_array() || val.size() == 0 || val[0].size() == 0)
        {
            return matrix_type{};
        }
        std::size_t cols = val[0].size();
        matrix_type m(val.size(), cols);
        
        for (std::size_t i = 0; i < val.size(); ++i)
        {
            const Json& row = val[i];
            if (row.size() != cols)
            {
                return matrix_type{};
            }
            for (std::size_t j = 0; j < row.size(); ++j)
            {
                m(i,j) = row[j].as<Scalar>();
            }
        }
        
        return m;
    }
    static Json to_json(const matrix_type& m, const allocator_type& alloc = allocator_type{})
    {
        Json val{ jsoncons::json_array_arg, alloc };
        for (Eigen::Index i = 0; i < m.rows(); ++i)
        {
            Json row{ jsoncons::json_array_arg };
            for (Eigen::Index j = 0; j < m.cols(); ++j)
            {
                row.push_back(m(i, j));
            }
            val.push_back(std::move(row));
        }
        return val;
    }
};
} // namespace jsonconsThen you can convert to/from a      Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> m = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>::Random(3, 4);
    std::cout << "m: " << std::endl << m << std::endl;
    jsoncons::json j{ m };
    std::cout << jsoncons::pretty_print(j) << "\n";
    assert((j.is<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>>()));
    auto m2 = j.as<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>>();
    std::cout << "m2: " << std::endl << m2 << std::endl;
    assert(m2 == m);or     Eigen::Matrix<double, 3, 4> m = Eigen::Matrix<double, 3, 4>::Random(3, 4);
    std::cout << "m: " << std::endl << m << std::endl;
    jsoncons::json j{ m };
    std::cout << jsoncons::pretty_print(j) << "\n";
    assert((j.is<Eigen::Matrix<double, 3, 4>>()));
    auto m2 = j.as<Eigen::Matrix<double, 3, 4>>();
    std::cout << "m2: " << std::endl << m2 << std::endl;
    assert(m2 == m); | 
Beta Was this translation helpful? Give feedback.
                  
                    1 reply
                  
                
            
      Answer selected by
        recsater
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment
  
        
    
Apologies, just got to this.
I would suggest defining separate
json_type_traitsstructs for the dynamic and fixed row/column cases. Something like this