Feature - TypedJsonJacksonCodec added. #1740

pull/1792/head
Nikita Koksharov 6 years ago
parent f7b0328c33
commit 365731758f

@ -33,7 +33,7 @@ import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
/**
* Type based codec for RMap objects
* @deprecated Use org.redisson.codec.TypedJsonJacksonCodec instead
*
* @author Nikita Koksharov
* @author Andrej Kazakov

@ -0,0 +1,170 @@
/**
* Copyright 2018 Nikita Koksharov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.redisson.codec;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.redisson.client.handler.State;
import org.redisson.client.protocol.Decoder;
import org.redisson.client.protocol.Encoder;
import org.redisson.codec.JsonJacksonCodec;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
/**
* Json Jackson Type codec. Doesn't include `@class` field during data encoding, and doesn't require it for data decoding.
*
* @author Nikita Koksharov
* @author Andrej Kazakov
*
*/
public class TypedJsonJacksonCodec extends JsonJacksonCodec {
private final Encoder encoder = new Encoder() {
@Override
public ByteBuf encode(Object in) throws IOException {
ByteBuf out = ByteBufAllocator.DEFAULT.buffer();
try {
ByteBufOutputStream os = new ByteBufOutputStream(out);
mapObjectMapper.writeValue((OutputStream)os, in);
return os.buffer();
} catch (IOException e) {
out.release();
throw e;
}
}
};
private Decoder<Object> createDecoder(final Class<?> valueClass, final TypeReference<?> valueTypeReference) {
return new Decoder<Object>() {
@Override
public Object decode(ByteBuf buf, State state) throws IOException {
if (valueClass != null) {
return mapObjectMapper.readValue((InputStream)new ByteBufInputStream(buf), valueClass);
}
if (valueTypeReference != null) {
return mapObjectMapper.readValue((InputStream)new ByteBufInputStream(buf), valueTypeReference);
}
return mapObjectMapper.readValue((InputStream)new ByteBufInputStream(buf), Object.class);
}
};
}
private final Decoder<Object> valueDecoder;
private final Decoder<Object> mapValueDecoder;
private final Decoder<Object> mapKeyDecoder;
public TypedJsonJacksonCodec(Class<?> valueClass) {
this(valueClass, new ObjectMapper());
}
public TypedJsonJacksonCodec(Class<?> valueClass, ObjectMapper mapper) {
this(valueClass, null, null, mapper);
}
public TypedJsonJacksonCodec(Class<?> mapKeyClass, Class<?> mapValueClass) {
this(null, mapKeyClass, mapValueClass, new ObjectMapper());
}
public TypedJsonJacksonCodec(Class<?> mapKeyClass, Class<?> mapValueClass, ObjectMapper mapper) {
this(null, mapKeyClass, mapValueClass, mapper);
}
public TypedJsonJacksonCodec(Class<?> valueClass, Class<?> mapKeyClass, Class<?> mapValueClass) {
this(null, null, null, valueClass, mapKeyClass, mapValueClass, new ObjectMapper());
}
public TypedJsonJacksonCodec(Class<?> valueClass, Class<?> mapKeyClass, Class<?> mapValueClass, ObjectMapper mapper) {
this(null, null, null, valueClass, mapKeyClass, mapValueClass, mapper);
}
public TypedJsonJacksonCodec(TypeReference<?> valueTypeReference) {
this(valueTypeReference, new ObjectMapper());
}
public TypedJsonJacksonCodec(TypeReference<?> valueTypeReference, ObjectMapper mapper) {
this(valueTypeReference, null, null, mapper);
}
public TypedJsonJacksonCodec(TypeReference<?> mapKeyTypeReference, TypeReference<?> mapValueTypeReference) {
this(null, mapKeyTypeReference, mapValueTypeReference);
}
public TypedJsonJacksonCodec(TypeReference<?> mapKeyTypeReference, TypeReference<?> mapValueTypeReference, ObjectMapper mapper) {
this(null, mapKeyTypeReference, mapValueTypeReference, mapper);
}
public TypedJsonJacksonCodec(TypeReference<?> valueTypeReference, TypeReference<?> mapKeyTypeReference, TypeReference<?> mapValueTypeReference) {
this(valueTypeReference, mapKeyTypeReference, mapValueTypeReference, null, null, null, new ObjectMapper());
}
public TypedJsonJacksonCodec(TypeReference<?> valueTypeReference, TypeReference<?> mapKeyTypeReference, TypeReference<?> mapValueTypeReference, ObjectMapper mapper) {
this(valueTypeReference, mapKeyTypeReference, mapValueTypeReference, null, null, null, mapper);
}
TypedJsonJacksonCodec(
TypeReference<?> valueTypeReference, TypeReference<?> mapKeyTypeReference, TypeReference<?> mapValueTypeReference,
Class<?> valueClass, Class<?> mapKeyClass, Class<?> mapValueClass, ObjectMapper mapper) {
super(mapper);
this.mapValueDecoder = createDecoder(mapValueClass, mapValueTypeReference);
this.mapKeyDecoder = createDecoder(mapKeyClass, mapKeyTypeReference);
this.valueDecoder = createDecoder(valueClass, valueTypeReference);
}
@Override
protected void initTypeInclusion(ObjectMapper mapObjectMapper) {
// avoid type inclusion
}
@Override
public Decoder<Object> getValueDecoder() {
return valueDecoder;
}
@Override
public Encoder getValueEncoder() {
return encoder;
}
@Override
public Decoder<Object> getMapKeyDecoder() {
return mapKeyDecoder;
}
@Override
public Encoder getMapValueEncoder() {
return encoder;
}
@Override
public Encoder getMapKeyEncoder() {
return encoder;
}
@Override
public Decoder<Object> getMapValueDecoder() {
return mapValueDecoder;
}
}

@ -1,4 +1,4 @@
package org.redisson.client.codec;
package org.redisson.codec;
import static org.assertj.core.api.Assertions.assertThat;
@ -10,6 +10,7 @@ import java.util.Map;
import org.junit.Test;
import org.redisson.BaseTest;
import org.redisson.api.RBucket;
import org.redisson.api.RMap;
import org.redisson.client.handler.State;
@ -17,16 +18,39 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.buffer.ByteBufAllocator;
import io.netty.util.CharsetUtil;
public class JsonJacksonMapValueCodecTest extends BaseTest {
public class TypedJsonJacksonCodecTest extends BaseTest {
private final JsonJacksonMapCodec mapCodec = new JsonJacksonMapCodec(null, new TypeReference<Map<String, List<String>>>() {
});
public static class Simple {
private String value;
private final JsonJacksonMapCodec stringCodec = new JsonJacksonMapCodec(null, String.class);
public Simple() {
}
public Simple(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
private final TypedJsonJacksonCodec valueCodec = new TypedJsonJacksonCodec(new TypeReference<Object>() {});
private final TypedJsonJacksonCodec mapCodec = new TypedJsonJacksonCodec(null, new TypeReference<Map<String, List<String>>>() {});
private final TypedJsonJacksonCodec stringCodec = new TypedJsonJacksonCodec(null, String.class);
private Simple value = new Simple("test");
private HashMap<String, List<String>> map = new HashMap<String, List<String>>();
{
@ -35,20 +59,34 @@ public class JsonJacksonMapValueCodecTest extends BaseTest {
@Test
public void testMap() {
RMap<String, byte[]> map = redisson.getMap("anyMap", new JsonJacksonMapCodec(String.class, byte[].class));
RMap<String, byte[]> map = redisson.getMap("anyMap", new TypedJsonJacksonCodec(String.class, byte[].class));
map.put(String.valueOf("2"), new byte[]{1, 2, 3});
assertThat(map.get("2")).isEqualTo(new byte[] {1, 2, 3});
}
@Test
public void testBucket() {
RBucket<String> bucket = redisson.getBucket("anyMap", new TypedJsonJacksonCodec(String.class));
bucket.set(String.valueOf("2"));
assertThat(bucket.get()).isEqualTo("2");
}
@Test
public void shouldDeserializeTheMapCorrectly() throws Exception {
ByteBuf buf = new PooledByteBufAllocator(true).buffer();
ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
buf.writeBytes(new ObjectMapper().writeValueAsBytes(map));
assertThat(mapCodec.getMapValueDecoder().decode(buf, new State(false)))
.isInstanceOf(Map.class)
.isEqualTo(map);
buf.release();
}
@Test
public void shouldSerializeValueCorrectly() throws Exception {
assertThat(valueCodec.getValueEncoder().encode(value).toString(CharsetUtil.UTF_8))
.isEqualTo("{\"value\":\"test\"}");
}
@Test
public void shouldSerializeTheMapCorrectly() throws Exception {
assertThat(mapCodec.getMapValueEncoder().encode(map).toString(CharsetUtil.UTF_8))
@ -57,11 +95,12 @@ public class JsonJacksonMapValueCodecTest extends BaseTest {
@Test
public void shouldDeserializeTheStringCorrectly() throws Exception {
ByteBuf buf = new PooledByteBufAllocator(true).buffer();
ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
buf.writeBytes(new ObjectMapper().writeValueAsBytes("axk"));
assertThat(stringCodec.getMapValueDecoder().decode(buf, new State(false)))
.isInstanceOf(String.class)
.isEqualTo("axk");
buf.release();
}
@Test
Loading…
Cancel
Save