msgpack java_让java版msgpack支持Object类型

msgpack是一种高效的二进制序列化格式,官方链接提供了很多中语言的实现,Java作为常用的开发语言之一,官方也提供了支持。

Java版的实现官方也提供了一些QuickStart教程,这里就不多说了,主要说下之前遇到的一个问题,由于某个POJO对象里含有Map类型的成员,在使用msgpack进行序列化和反序列化时,出现了一些奇怪的现象,比如反序列化出来的Map在进行get时无法表现出正常的操作,虽然Debug时看到内存里确实有数据。后来简单分析了一下发现,在没有指定模板类型时,msgpack反序列化出来的Map实际上是其Jar包内自己封装的一个Map实现类,所以就会出现上述的情况,要解决这个问题,就需要在反序列化解析时,给msgpack明确指定模板类型。

msgpack的内置提供了很多模板,其中就有MapTemplate,这是一个泛型类,在构造时需要指定key和val的模板类型,而msgpack并没有内置Object的模板,所以当如果需要序列化和反序列化一个Value是Object的Map时,就会出现问题。因此我们需要自己来实现一个Object的模板,代码如下:

public class ObjectTemplate extends AbstractTemplate {

private ObjectTemplate() {

}

static public ObjectTemplate getInstance() {

return instance;

}

static final ObjectTemplate instance = new ObjectTemplate();

@Override

public void write(Packer pk, Object v, boolean required) throws IOException {

if (v == null) {

if (required) {

throw new MessageTypeException("Attempted to write null");

}

pk.writeNil();

return;

}

pk.write(v);

}

@Override

public Object read(Unpacker u, Object to, boolean required) throws IOException {

if (!required && u.trySkipNil()) {

return null;

}

return toObject(u.readValue());

}

private static Object toObject(Value value) throws IOException {

Converter conv = new Converter(value);

if (value.isNilValue()) { // null

return null;

} else if (value.isRawValue()) { // byte[] or String or maybe Date?

// deserialize value to String object

RawValue v = value.asRawValue();

return conv.read(Templates.TString);

} else if (value.isBooleanValue()) { // boolean

return conv.read(Templates.TBoolean);

} else if (value.isIntegerValue()) { // int or long or BigInteger

// deserialize value to int

IntegerValue v = value.asIntegerValue();

return conv.read(Templates.TInteger);

} else if (value.isFloatValue()) { // float or double

// deserialize value to double

FloatValue v = value.asFloatValue();

return conv.read(Templates.TDouble);

} else if (value.isArrayValue()) { // List or Set

// deserialize value to List object

ArrayValue v = value.asArrayValue();

List ret = new ArrayList(v.size());

for (Value elementValue : v) {

ret.add(toObject(elementValue));

}

return ret;

} else if (value.isMapValue()) { // Map

MapValue v = value.asMapValue();

Map map = new HashMap<>(v.size());

for (Map.Entry entry : v.entrySet()) {

Value key = entry.getKey();

Value val = entry.getValue();

map.put(toObject(key), toObject(val));

}

return map;

} else {

throw new RuntimeException("fatal error");

}

}

}

以上代码在issue4的基础上增加了支持基本类型作为K-V的Map的嵌套,我测试了三层嵌套Map是可以的,更深层的没有去测试,不过一般使用也应该够用了。以上模板在使用msgpack进行read和write时作为参数传递进去即可,如下面的例子 :

MessagePack pack = new MessagePack();

byte[] bytes = pack.write(map);

Map m = pack.read(bytes, Templates.tMap(Templates.TInteger, ObjectTemplate.getInstance()));

总体来说msgpack还是很好用的,所以在当我们用一个开源项目遇到问题时,先最好多看看文档和源码,很多时候就能解决我们遇到的问题,而不是过多的抱怨

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/v1/object.hpp:664:34: error: ‘void* memcpy(void*, const void*, size_t)’ copying an object of non-trivial type ‘struct msgpack::v2::object’ from an array of ‘const msgpack_object’ {aka ‘const struct msgpack_object’} [-Werror=class-memaccess] std::memcpy(&o, &v, sizeof(v)); ^ In file included from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/object_fwd.hpp:17, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/v1/adaptor/adaptor_base_decl.hpp:14, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/adaptor/adaptor_base_decl.hpp:13, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/adaptor/adaptor_base.hpp:13, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/v1/object_decl.hpp:16, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/object_decl.hpp:14, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/object.hpp:13, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack.hpp:10, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/example/cpp03/stream.cpp:10: /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/v2/object_fwd.hpp:23:8: note: ‘struct msgpack::v2::object’ declared here struct object : v1::object { ^~~~~~ cc1plus: all warnings being treated as errors make[2]: *** [example/cpp03/CMakeFiles/stream.dir/build.make:63:example/cpp03/CMakeFiles/stream.dir/stream.cpp.o] 错误 1 make[2]: 离开目录“/home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master” make[1]: *** [CMakeFiles/Makefile2:415:example/cpp03/CMakeFiles/stream.dir/all] 错误 2 make[1]: 离开目录“/home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master”
07-20

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值