-
Notifications
You must be signed in to change notification settings - Fork 324
Description
Currently we can deserialize an ExtendedType into a MessagePackExtendedType with an ObjectMapper from the getEmbbededObject method in MessagePackParser
One way of deserializing the object would be to have an customer deserializer. The following is an example of that where we have a java class called Buffer that is represented as an extension type where the extType is called bufferType. The contents of the extension type is just a Message Packed integer.
module.addDeserializer(Buffer.class, new JsonDeserializer<Buffer>() {
@Override
public Class<Buffer> handledType() {
return Buffer.class;
}
@Override
public Buffer deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
MessagePackExtendedType extendedType = (MessagePackExtendedType) jsonParser.getEmbeddedObject();
if (extendedType.extType() != bufferType) {
throw new IllegalStateException("extendedType != bufferType");
}
byte[] b = new byte[extendedType.byteBuffer().remaining()];
extendedType.byteBuffer().get(b);
long id = MessagePack.newDefaultUnpacker(b).getCursor().nextRef().asInteger().asLong();
return new Buffer(id);
}
});
This to me feels brittle since the object deserializer has guessed the extType before reading it. If it guessed wrong it just throws an exception.
I think a more robust solution would be to have getEmbeddedObejct return the Buffer class itself. However I don't know if this is any better.
On the other side, there does not appear to be any way to serialize a class into an Extended Type. If we add a writeExtendedType to the MessagePackGenearator class we could add a custom serializer such as the following.
module.addSerializer(Buffer.class, new JsonSerializer<Buffer>() {
@Override
public Class<Buffer> handledType() {
return Buffer.class;
}
@Override
public void serialize(Buffer buffer,
JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
MessagePackGenerator generator = (MessagePackGenerator) jsonGenerator;
ByteArrayOutputStream out = new ByteArrayOutputStream();
MessagePack.newDefaultPacker(out)
.packLong(buffer.getId())
.close();
MessagePackExtendedType extendedType =
new MessagePackExtendedType(bufferType, ByteBuffer.wrap(out.toByteArray()));
generator.writeExtendedType(extendedType);
}
});
Where writeExtendedType was made using the following patch
diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java
index bc23e13..0375c27 100644
--- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java
+++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java
@@ -175,6 +175,12 @@ public class MessagePackGenerator extends GeneratorBase {
else if (v instanceof Boolean) {
messagePacker.packBoolean((Boolean) v);
}
+ else if (v instanceof MessagePackExtendedType) {
+ MessagePackExtendedType extendedType = (MessagePackExtendedType) v;
+ ByteBuffer buf = extendedType.byteBuffer();
+ messagePacker.packExtendedTypeHeader(extendedType.extType(), buf.remaining());
+ messagePacker.writePayload(buf);
+ }
else {
throw new IllegalArgumentException(v.toString());
}
@@ -324,6 +330,10 @@ public class MessagePackGenerator extends GeneratorBase {
addValueToStackTop(null);
}
+ public void writeExtendedType(MessagePackExtendedType extendedType) {
+ addValueToStackTop(extendedType);
+ }
+
@Override
public void close() throws IOException {
try {
I'm not sure if this is the best way to handle this though.
What should the canonical way to serialize and deserialize extended types with the jackson api be?