From 141ca2c5851ad4a93521b202f54231e9c3a15a13 Mon Sep 17 00:00:00 2001 From: andrejserafim Date: Sat, 2 Jul 2016 22:10:40 +0100 Subject: [PATCH] a basic typed map value codec. Closed #532. See RedissonCodecTest for usage examples. I've had to change JsonJacksonCodec to use decoder, encoder members explicitly otherwise overriding just the map value ones would override all of them. Also rearranged the methods in RedissonCodecTest, so they make more sense - test() method last. --- .../codec/JsonJacksonMapValueCodec.java | 47 ++++++++++++ .../org/redisson/codec/JsonJacksonCodec.java | 27 +++---- .../java/org/redisson/RedissonCodecTest.java | 71 ++++++++++++------- .../codec/JsonJacksonMapValueCodecTest.java | 63 ++++++++++++++++ 4 files changed, 166 insertions(+), 42 deletions(-) create mode 100644 src/main/java/org/redisson/client/codec/JsonJacksonMapValueCodec.java create mode 100644 src/test/java/org/redisson/client/codec/JsonJacksonMapValueCodecTest.java diff --git a/src/main/java/org/redisson/client/codec/JsonJacksonMapValueCodec.java b/src/main/java/org/redisson/client/codec/JsonJacksonMapValueCodec.java new file mode 100644 index 000000000..33f06b086 --- /dev/null +++ b/src/main/java/org/redisson/client/codec/JsonJacksonMapValueCodec.java @@ -0,0 +1,47 @@ +package org.redisson.client.codec; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import org.redisson.client.handler.State; +import org.redisson.client.protocol.Decoder; +import org.redisson.client.protocol.Encoder; +import org.redisson.codec.JsonJacksonCodec; + +import java.io.IOException; + +public class JsonJacksonMapValueCodec extends JsonJacksonCodec { + private final ObjectMapper mapper; + private TypeReference typeReference; + + public JsonJacksonMapValueCodec(Class klass) { + this(new TypeReference() { + }); + } + + public JsonJacksonMapValueCodec(TypeReference typeReference) { + this.typeReference = typeReference; + this.mapper = initObjectMapper(); + } + + @Override + public Decoder getMapValueDecoder() { + return new Decoder() { + @Override + public Object decode(ByteBuf buf, State state) throws IOException { + return mapper.readValue(new ByteBufInputStream(buf), typeReference); + } + }; + } + + @Override + public Encoder getMapValueEncoder() { + return new Encoder() { + @Override + public byte[] encode(Object in) throws IOException { + return mapper.writeValueAsBytes(in); + } + }; + } +} \ No newline at end of file diff --git a/src/main/java/org/redisson/codec/JsonJacksonCodec.java b/src/main/java/org/redisson/codec/JsonJacksonCodec.java index 342ad33fe..1cfe91c33 100755 --- a/src/main/java/org/redisson/codec/JsonJacksonCodec.java +++ b/src/main/java/org/redisson/codec/JsonJacksonCodec.java @@ -15,21 +15,10 @@ */ package org.redisson.codec; -import java.io.IOException; - -import org.redisson.client.codec.Codec; -import org.redisson.client.handler.State; -import org.redisson.client.protocol.Decoder; -import org.redisson.client.protocol.Encoder; - import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.JsonIdentityInfo; -import com.fasterxml.jackson.annotation.JsonIdentityReference; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.databind.DeserializationFeature; @@ -39,11 +28,15 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTypeResolverBuilder; import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver; import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; - import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufInputStream; +import org.redisson.client.codec.Codec; +import org.redisson.client.handler.State; +import org.redisson.client.protocol.Decoder; +import org.redisson.client.protocol.Encoder; + +import java.io.IOException; /** * @@ -141,22 +134,22 @@ public class JsonJacksonCodec implements Codec { @Override public Decoder getMapKeyDecoder() { - return getMapValueDecoder(); + return decoder; } @Override public Encoder getMapKeyEncoder() { - return getMapValueEncoder(); + return encoder; } @Override public Decoder getValueDecoder() { - return getMapValueDecoder(); + return decoder; } @Override public Encoder getValueEncoder() { - return getMapValueEncoder(); + return encoder; } } diff --git a/src/test/java/org/redisson/RedissonCodecTest.java b/src/test/java/org/redisson/RedissonCodecTest.java index f713bdc7c..60c2c3429 100644 --- a/src/test/java/org/redisson/RedissonCodecTest.java +++ b/src/test/java/org/redisson/RedissonCodecTest.java @@ -1,14 +1,10 @@ package org.redisson; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - +import com.fasterxml.jackson.core.type.TypeReference; import org.junit.Assert; import org.junit.Test; import org.redisson.client.codec.Codec; +import org.redisson.client.codec.JsonJacksonMapValueCodec; import org.redisson.codec.CborJacksonCodec; import org.redisson.codec.FstCodec; import org.redisson.codec.JsonJacksonCodec; @@ -19,6 +15,15 @@ import org.redisson.codec.SerializationCodec; import org.redisson.codec.SnappyCodec; import org.redisson.core.RMap; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + public class RedissonCodecTest extends BaseTest { private Codec codec = new SerializationCodec(); private Codec kryoCodec = new KryoCodec(); @@ -28,6 +33,8 @@ public class RedissonCodecTest extends BaseTest { private Codec snappyCodec = new SnappyCodec(); private Codec msgPackCodec = new MsgPackJacksonCodec(); private Codec lz4Codec = new LZ4Codec(); + private Codec jsonListOfStringCodec = new JsonJacksonMapValueCodec>(new TypeReference>() { + }); @Test public void testLZ4() { @@ -83,6 +90,39 @@ public class RedissonCodecTest extends BaseTest { test(); } + @Test + public void testKryo() { + Config config = createConfig(); + config.setCodec(kryoCodec); + redisson = Redisson.create(config); + + test(); + } + + @Test + public void testCbor() { + Config config = createConfig(); + config.setCodec(cborCodec); + redisson = Redisson.create(config); + + test(); + + } + + @Test + public void testListOfStrings() { + Config config = createConfig(); + config.setCodec(new JsonJacksonCodec()); + redisson = Redisson.create(config); + + RMap> map = redisson.getMap("list of strings", jsonListOfStringCodec); + map.put("foo", new ArrayList(Arrays.asList("bar"))); + + RMap> map2 = redisson.getMap("list of strings", jsonListOfStringCodec); + + assertThat(map2).isEqualTo(map); + } + public void test() { RMap> map = redisson.getMap("getAll"); Map a = new HashMap(); @@ -111,23 +151,4 @@ public class RedissonCodecTest extends BaseTest { Assert.assertTrue(set.contains(new TestObject("1", "2"))); Assert.assertFalse(set.contains(new TestObject("1", "9"))); } - - @Test - public void testKryo() { - Config config = createConfig(); - config.setCodec(kryoCodec); - redisson = Redisson.create(config); - - test(); - } - - @Test - public void testCbor() { - Config config = createConfig(); - config.setCodec(cborCodec); - redisson = Redisson.create(config); - - test(); - - } } diff --git a/src/test/java/org/redisson/client/codec/JsonJacksonMapValueCodecTest.java b/src/test/java/org/redisson/client/codec/JsonJacksonMapValueCodecTest.java new file mode 100644 index 000000000..b0d4b4ebe --- /dev/null +++ b/src/test/java/org/redisson/client/codec/JsonJacksonMapValueCodecTest.java @@ -0,0 +1,63 @@ +package org.redisson.client.codec; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.PooledByteBufAllocator; +import org.junit.Before; +import org.junit.Test; +import org.redisson.client.handler.State; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +public class JsonJacksonMapValueCodecTest { + + private final JsonJacksonMapValueCodec>> mapCodec = new JsonJacksonMapValueCodec>>(new TypeReference>>() { + }); + + private final JsonJacksonMapValueCodec stringCodec = new JsonJacksonMapValueCodec(String.class); + + private HashMap> map; + + @Before + public void setUp() throws Exception { + map = new HashMap>(); + map.put("foo", new ArrayList(Arrays.asList("bar"))); + } + + @Test + public void shouldDeserializeTheMapCorrectly() throws Exception { + ByteBuf buf = new PooledByteBufAllocator(true).buffer(); + buf.writeBytes(new ObjectMapper().writeValueAsBytes(map)); + assertThat(mapCodec.getMapValueDecoder().decode(buf, new State(false))) + .isInstanceOf(Map.class) + .isEqualTo(map); + } + + @Test + public void shouldSerializeTheMapCorrectly() throws Exception { + assertThat(new String(mapCodec.getMapValueEncoder().encode(map), "UTF-8")) + .isEqualTo("{\"foo\":[\"bar\"]}"); + } + + @Test + public void shouldDeserializeTheStringCorrectly() throws Exception { + ByteBuf buf = new PooledByteBufAllocator(true).buffer(); + buf.writeBytes(new ObjectMapper().writeValueAsBytes("axk")); + assertThat(stringCodec.getMapValueDecoder().decode(buf, new State(false))) + .isInstanceOf(String.class) + .isEqualTo("axk"); + } + + @Test + public void shouldSerializeTheStringCorrectly() throws Exception { + assertThat(new String(stringCodec.getMapValueEncoder().encode("foo"), "UTF-8")) + .isEqualTo("\"foo\""); + } +} \ No newline at end of file