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 jsoncons Then 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_traits
structs for the dynamic and fixed row/column cases. Something like this