Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 150 additions & 8 deletions msgpack-jackson/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,16 +207,15 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial
@JsonSerialize(keyUsing = MessagePackKeySerializer.class)
private Map<Integer, String> intMap = new HashMap<>();

:
{
intMap.put(42, "Hello");
:

ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
byte[] bytes = objectMapper.writeValueAsBytes(intMap);
intMap.put(42, "Hello");

Map<Integer, String> deserialized = objectMapper.readValue(bytes, new TypeReference<Map<Integer, String>>() {});
System.out.println(deserialized); // => {42=Hello}
}
ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
byte[] bytes = objectMapper.writeValueAsBytes(intMap);

Map<Integer, String> deserialized = objectMapper.readValue(bytes, new TypeReference<Map<Integer, String>>() {});
System.out.println(deserialized); // => {42=Hello}
```

### Deserialize extension types with ExtensionTypeCustomDeserializers
Expand Down Expand Up @@ -316,6 +315,149 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial
// => Java
```

#### Use extension type as Map key

```java
static class TripleBytesPojo
{
public byte first;
public byte second;
public byte third;

public TripleBytesPojo(byte first, byte second, byte third)
{
this.first = first;
this.second = second;
this.third = third;
}

@Override
public boolean equals(Object o)
{
:
}

@Override
public int hashCode()
{
:
}

@Override
public String toString()
{
// This key format is used when serialized as map key
return String.format("%d-%d-%d", first, second, third);
}

static class KeyDeserializer
extends com.fasterxml.jackson.databind.KeyDeserializer
{
@Override
public Object deserializeKey(String key, DeserializationContext ctxt)
throws IOException
{
String[] values = key.split("-");
return new TripleBytesPojo(Byte.parseByte(values[0]), Byte.parseByte(values[1]), Byte.parseByte(values[2]));
}
}

static TripleBytesPojo deserialize(byte[] bytes)
{
return new TripleBytesPojo(bytes[0], bytes[1], bytes[2]);
}
}

:

byte extTypeCode = 42;

ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers();
extTypeCustomDesers.addCustomDeser(extTypeCode, new ExtensionTypeCustomDeserializers.Deser()
{
@Override
public Object deserialize(byte[] value)
throws IOException
{
return TripleBytesPojo.deserialize(value);
}
});

SimpleModule module = new SimpleModule();
module.addKeyDeserializer(TripleBytesPojo.class, new TripleBytesPojo.KeyDeserializer());
ObjectMapper objectMapper = new ObjectMapper(
new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers))
.registerModule(module);

Map<TripleBytesPojo, Integer> deserializedMap =
objectMapper.readValue(serializedData,
new TypeReference<Map<TripleBytesPojo, Integer>>() {});
```

#### Use extension type as Map value

```java
static class TripleBytesPojo
{
public byte first;
public byte second;
public byte third;

public TripleBytesPojo(byte first, byte second, byte third)
{
this.first = first;
this.second = second;
this.third = third;
}

static class Deserializer
extends StdDeserializer<TripleBytesPojo>
{
protected Deserializer()
{
super(TripleBytesPojo.class);
}

@Override
public TripleBytesPojo deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
return TripleBytesPojo.deserialize(p.getBinaryValue());
}
}

static TripleBytesPojo deserialize(byte[] bytes)
{
return new TripleBytesPojo(bytes[0], bytes[1], bytes[2]);
}
}

:

byte extTypeCode = 42;

ExtensionTypeCustomDeserializers extTypeCustomDesers = new ExtensionTypeCustomDeserializers();
extTypeCustomDesers.addCustomDeser(extTypeCode, new ExtensionTypeCustomDeserializers.Deser()
{
@Override
public Object deserialize(byte[] value)
throws IOException
{
return TripleBytesPojo.deserialize(value);
}
});

SimpleModule module = new SimpleModule();
module.addDeserializer(TripleBytesPojo.class, new TripleBytesPojo.Deserializer());
ObjectMapper objectMapper = new ObjectMapper(
new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers))
.registerModule(module);

Map<String, TripleBytesPojo> deserializedMap =
objectMapper.readValue(serializedData,
new TypeReference<Map<String, TripleBytesPojo>>() {});
```

### Serialize a nested object that also serializes

When you serialize an object that has a nested object also serializing with ObjectMapper and MessagePackFactory like the following code, it throws NullPointerException since the nested MessagePackFactory modifies a shared state stored in ThreadLocal.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,13 @@ public JsonToken nextToken()
type = Type.EXT;
ExtensionTypeHeader header = messageUnpacker.unpackExtensionTypeHeader();
extensionTypeValue = new MessagePackExtensionType(header.getType(), messageUnpacker.readPayload(header.getLength()));
nextToken = JsonToken.VALUE_EMBEDDED_OBJECT;
if (parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) {
parsingContext.setCurrentName(deserializedExtensionTypeValue().toString());
nextToken = JsonToken.FIELD_NAME;
}
else {
nextToken = JsonToken.VALUE_EMBEDDED_OBJECT;
}
break;
default:
throw new IllegalStateException("Shouldn't reach here");
Expand Down Expand Up @@ -391,6 +397,8 @@ public String getText()
return String.valueOf(doubleValue);
case BIG_INT:
return String.valueOf(biValue);
case EXT:
return deserializedExtensionTypeValue().toString();
default:
throw new IllegalStateException("Invalid type=" + type);
}
Expand Down Expand Up @@ -432,6 +440,8 @@ public byte[] getBinaryValue(Base64Variant b64variant)
return bytesValue;
case STRING:
return stringValue.getBytes(MessagePack.UTF8);
case EXT:
return extensionTypeValue.getData();
default:
throw new IllegalStateException("Invalid type=" + type);
}
Expand Down Expand Up @@ -563,6 +573,18 @@ public BigDecimal getDecimalValue()
}
}

private Object deserializedExtensionTypeValue()
throws IOException
{
if (extTypeCustomDesers != null) {
ExtensionTypeCustomDeserializers.Deser deser = extTypeCustomDesers.getDeser(extensionTypeValue.getType());
if (deser != null) {
return deser.deserialize(extensionTypeValue.getData());
}
}
return extensionTypeValue;
}

@Override
public Object getEmbeddedObject()
throws IOException, JsonParseException
Expand All @@ -571,13 +593,7 @@ public Object getEmbeddedObject()
case BYTES:
return bytesValue;
case EXT:
if (extTypeCustomDesers != null) {
ExtensionTypeCustomDeserializers.Deser deser = extTypeCustomDesers.getDeser(extensionTypeValue.getType());
if (deser != null) {
return deser.deserialize(extensionTypeValue.getData());
}
}
return extensionTypeValue;
return deserializedExtensionTypeValue();
default:
throw new IllegalStateException("Invalid type=" + type);
}
Expand Down
Loading