使用nlohmann json的to_json方法将Eigen矩阵写入json文件。

huangapple go评论126阅读模式
英文:

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

问题

我定义了一个Eigen矩阵 - 

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

我尝试将Vec3d写入JSON文件,如下所示 -

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

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

输出以array的形式存储,而不是如to_json中指定的方式,似乎没有进入to_json??

"Vec3d": [
 1.0,
 2.0,
 3.0
]

但我想要的是像to_json中指定的方式,如下所示 -

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

在实现模板化的to_json中是否有问题?如何使其工作。

PS:还有,读取时,模板化的adl_serializer from_json()会是什么样子?


<details>
<summary>英文:</summary>

I have an Eigen matrix defined - 

    template &lt;typename T&gt;
    using Vec3 = Eigen::Matrix&lt;T, 1, 3, Eigen::DontAlign | Eigen::ColMajor&gt;;
    using Vec3d = Vec3&lt;double&gt;;

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` ??

    &quot;Vec3d&quot;: [
     1.0,
     2.0,
     3.0
    ]

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

    &quot;Vec3d&quot;: [
     &quot;X&quot;: 1.0,
     &quot;Y&quot;: 2.0,
     &quot;Z&quot;: 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 ?





</details>


# 答案1
**得分**: 2

我找不到默认的 `Eigen::Matrix` JSON 序列化器是如何实现的,但要使您的自定义序列化器起作用,只需将其放在 `Eigen` 命名空间内:

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

或者,如第三方类型序列化文档建议的,您可以编写 adl_serializer 特化版本:

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"];
        }
    };
}

通常情况下,第二种选项可能更可取,因为它不会污染您的第三方命名空间。

示例

英文:

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 &lt;typename T&gt;
    void to_json(json&amp; j, const Vec3&lt;T&gt;&amp; v) {
    j = {{&quot;X&quot;, v(0)}, {&quot;Y&quot;, v(1)}, {&quot;Z&quot;, v(2)}};
}

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

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

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

Demo

huangapple
  • 本文由 发表于 2023年7月31日 20:23:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76803591.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定