Msgpack 中是否有版本控制功能
Is there versioning capability in Msgpack
我正在评估 Msgpack(C++) 作为我当前项目中的序列化库。它似乎满足了我的大部分需求,除了一个,我没有在网上找到太多关于它的信息。 Msgpack 是否支持读取我将序列化的不同版本的数据结构?
例如,我序列化如下结构:
struct foo {
int a;
float b;
};
后来上面的结构演变成:
struct foo {
int a;
float b;
std::string c;
};
是否可以使用 Msgpack 将以前序列化的结构读入新结构? Boost 库通过添加 VERSION
元数据和结构来处理它。
是的,你可以做到。如果先打包foo_v1
再解包,再转换为foo_v2
,a
和b
填充的是打包值
#include <msgpack.hpp>
#include <cassert>
#include <iostream>
#include <sstream>
struct foo_v1 {
int a;
float b;
MSGPACK_DEFINE(a, b); // pack as ARRAY, order is important
};
struct foo_v2 {
int a;
float b;
std::string c;
MSGPACK_DEFINE(a, b, c); // pack as ARRAY, order is important
};
int main() {
foo_v1 v1 { 123, 45.67 };
std::stringstream ss;
msgpack::pack(ss, v1);
auto oh = msgpack::unpack(ss.str().data(), ss.str().size());
auto v2 = oh.get().as<foo_v2>();
std::cout << "a: " << v2.a << std::endl;
std::cout << "b: " << v2.b << std::endl;
std::cout << "c: " << v2.c << std::endl;
}
运行 演示:https://wandbox.org/permlink/91wRtVdJJCC5IEDx
同理,如果先打包foo_v2
再解包,再转换成foo_v1
,a
和b
填充的是打包值,c
被切片(忽略)。
#include <msgpack.hpp>
#include <cassert>
#include <iostream>
#include <sstream>
struct foo_v1 {
int a;
float b;
MSGPACK_DEFINE(a, b); // pack as ARRAY, order is important
};
struct foo_v2 {
int a;
float b;
std::string c;
MSGPACK_DEFINE(a, b, c); // pack as ARRAY, order is important
};
int main() {
foo_v2 v2 { 123, 45.67, "hello" };
std::stringstream ss;
msgpack::pack(ss, v2);
auto oh = msgpack::unpack(ss.str().data(), ss.str().size());
auto v1 = oh.get().as<foo_v1>();
std::cout << "a: " << v1.a << std::endl;
std::cout << "b: " << v1.b << std::endl;
}
运行 演示:https://wandbox.org/permlink/mxmSkVHebZFiOM1q
这些示例使用了 MSGPACK_DEFINE
宏。参见 https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor#defining-custom-adaptors。
默认情况下,packing/converting 作为 ARRAY。所以顺序很重要。
如果您使用 MSGPACK_DEFINE_MAP
,则用户 类 是 packing/converting 作为 MAP。 MAP
的key默认是变量名。您可以使用 MSGPACK_NVP
更改它,请参阅 https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor#since-210。 MAP
的值就是成员变量的值。
MAP
比 ARRAY
更灵活,但效率低下。
如果使用MSGPACK_DEFINE_MAP
,则无需关心顺序。
#include <msgpack.hpp>
#include <cassert>
#include <iostream>
#include <sstream>
struct foo_v1 {
int a;
float b;
MSGPACK_DEFINE_MAP(a, b); // pack as MAP
};
struct foo_v2 {
int a;
std::string c;
float b;
MSGPACK_DEFINE_MAP(a, c, b); // pack as MAP, c is at the middle position
};
int main() {
foo_v2 v2 { 123, "hello", 45.67, };
std::stringstream ss;
msgpack::pack(ss, v2);
auto oh = msgpack::unpack(ss.str().data(), ss.str().size());
auto v1 = oh.get().as<foo_v1>();
std::cout << "a: " << v1.a << std::endl;
std::cout << "b: " << v1.b << std::endl;
}
运行 演示:https://wandbox.org/permlink/ozihpwXMJRpOhzT4
这是更复杂的例子:
https://github.com/msgpack/msgpack-c/blob/master/example/cpp03/map_based_versionup.cpp
我正在评估 Msgpack(C++) 作为我当前项目中的序列化库。它似乎满足了我的大部分需求,除了一个,我没有在网上找到太多关于它的信息。 Msgpack 是否支持读取我将序列化的不同版本的数据结构?
例如,我序列化如下结构:
struct foo {
int a;
float b;
};
后来上面的结构演变成:
struct foo {
int a;
float b;
std::string c;
};
是否可以使用 Msgpack 将以前序列化的结构读入新结构? Boost 库通过添加 VERSION
元数据和结构来处理它。
是的,你可以做到。如果先打包foo_v1
再解包,再转换为foo_v2
,a
和b
填充的是打包值
#include <msgpack.hpp>
#include <cassert>
#include <iostream>
#include <sstream>
struct foo_v1 {
int a;
float b;
MSGPACK_DEFINE(a, b); // pack as ARRAY, order is important
};
struct foo_v2 {
int a;
float b;
std::string c;
MSGPACK_DEFINE(a, b, c); // pack as ARRAY, order is important
};
int main() {
foo_v1 v1 { 123, 45.67 };
std::stringstream ss;
msgpack::pack(ss, v1);
auto oh = msgpack::unpack(ss.str().data(), ss.str().size());
auto v2 = oh.get().as<foo_v2>();
std::cout << "a: " << v2.a << std::endl;
std::cout << "b: " << v2.b << std::endl;
std::cout << "c: " << v2.c << std::endl;
}
运行 演示:https://wandbox.org/permlink/91wRtVdJJCC5IEDx
同理,如果先打包foo_v2
再解包,再转换成foo_v1
,a
和b
填充的是打包值,c
被切片(忽略)。
#include <msgpack.hpp>
#include <cassert>
#include <iostream>
#include <sstream>
struct foo_v1 {
int a;
float b;
MSGPACK_DEFINE(a, b); // pack as ARRAY, order is important
};
struct foo_v2 {
int a;
float b;
std::string c;
MSGPACK_DEFINE(a, b, c); // pack as ARRAY, order is important
};
int main() {
foo_v2 v2 { 123, 45.67, "hello" };
std::stringstream ss;
msgpack::pack(ss, v2);
auto oh = msgpack::unpack(ss.str().data(), ss.str().size());
auto v1 = oh.get().as<foo_v1>();
std::cout << "a: " << v1.a << std::endl;
std::cout << "b: " << v1.b << std::endl;
}
运行 演示:https://wandbox.org/permlink/mxmSkVHebZFiOM1q
这些示例使用了 MSGPACK_DEFINE
宏。参见 https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor#defining-custom-adaptors。
默认情况下,packing/converting 作为 ARRAY。所以顺序很重要。
如果您使用 MSGPACK_DEFINE_MAP
,则用户 类 是 packing/converting 作为 MAP。 MAP
的key默认是变量名。您可以使用 MSGPACK_NVP
更改它,请参阅 https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor#since-210。 MAP
的值就是成员变量的值。
MAP
比 ARRAY
更灵活,但效率低下。
如果使用MSGPACK_DEFINE_MAP
,则无需关心顺序。
#include <msgpack.hpp>
#include <cassert>
#include <iostream>
#include <sstream>
struct foo_v1 {
int a;
float b;
MSGPACK_DEFINE_MAP(a, b); // pack as MAP
};
struct foo_v2 {
int a;
std::string c;
float b;
MSGPACK_DEFINE_MAP(a, c, b); // pack as MAP, c is at the middle position
};
int main() {
foo_v2 v2 { 123, "hello", 45.67, };
std::stringstream ss;
msgpack::pack(ss, v2);
auto oh = msgpack::unpack(ss.str().data(), ss.str().size());
auto v1 = oh.get().as<foo_v1>();
std::cout << "a: " << v1.a << std::endl;
std::cout << "b: " << v1.b << std::endl;
}
运行 演示:https://wandbox.org/permlink/ozihpwXMJRpOhzT4
这是更复杂的例子: https://github.com/msgpack/msgpack-c/blob/master/example/cpp03/map_based_versionup.cpp