diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index cc5936163..1acd027b5 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -83,3 +83,15 @@ Java // xs => [zero, 1, 2.0, null] ``` +### Serialization format + +By default, the serialization format is object, which means it includes the schema of the serialized entity (POJO). +To serialize an entity without the schema, only as array, you can add the annotation `@JsonFormat(shape=JsonFormat.Shape.ARRAY)` to the entity definition. +Also, it's possible to set the serialization format for the object mapper instance to be array by changing the annotation inspector of object mapper to `JsonArrayFormat`: + +``` + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.setAnnotationIntrospector(new JsonArrayFormat()); +``` + +This format provides compatibility with msgpack-java 0.6.x serialization api. \ No newline at end of file diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JsonArrayFormat.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JsonArrayFormat.java new file mode 100644 index 000000000..c49290c07 --- /dev/null +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/JsonArrayFormat.java @@ -0,0 +1,31 @@ +package org.msgpack.jackson.dataformat; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.introspect.Annotated; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; + +import static com.fasterxml.jackson.annotation.JsonFormat.Shape.ARRAY; + +/** + * Provides the ability of serializing POJOs without their schema. + * Similar to @JsonFormat annotation with JsonFormat.Shape.ARRAY, but in a programmatic + * way. + * + * This also provides same behavior as msgpack-java 0.6.x serialization api. + */ +public class JsonArrayFormat extends JacksonAnnotationIntrospector +{ + private static final JsonFormat.Value ARRAY_FORMAT = new JsonFormat.Value().withShape(ARRAY); + + @Override + public JsonFormat.Value findFormat(Annotated ann) + { + // If the entity contains JsonFormat annotation, give it higher priority. + JsonFormat.Value precedenceFormat = super.findFormat(ann); + if (precedenceFormat != null) { + return precedenceFormat; + } + + return ARRAY_FORMAT; + } +} diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java index 5c1559770..c6b020686 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatForPojoTest.java @@ -15,13 +15,18 @@ // package org.msgpack.jackson.dataformat; +import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; import java.io.IOException; -import java.util.Arrays; +import java.nio.charset.Charset; + +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.containsString; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertArrayEquals; public class MessagePackDataformatForPojoTest extends MessagePackDataformatTestBase @@ -38,7 +43,7 @@ public void testNormal() assertEquals(normalPojo.l, value.l); assertEquals(normalPojo.f, value.f, 0.000001f); assertEquals(normalPojo.d, value.d, 0.000001f); - assertTrue(Arrays.equals(normalPojo.b, value.b)); + assertArrayEquals(normalPojo.b, value.b); assertEquals(normalPojo.bi, value.bi); assertEquals(normalPojo.suit, Suit.HEART); } @@ -50,7 +55,7 @@ public void testNestedList() byte[] bytes = objectMapper.writeValueAsBytes(nestedListPojo); NestedListPojo value = objectMapper.readValue(bytes, NestedListPojo.class); assertEquals(nestedListPojo.s, value.s); - assertTrue(Arrays.equals(nestedListPojo.strs.toArray(), value.strs.toArray())); + assertArrayEquals(nestedListPojo.strs.toArray(), value.strs.toArray()); } @Test @@ -99,4 +104,20 @@ public void testChangingPropertyNames() ChangingPropertyNamesPojo value = objectMapper.readValue(bytes, ChangingPropertyNamesPojo.class); assertEquals("komamitsu", value.getTheName()); } + + @Test + public void testSerializationWithoutSchema() + throws IOException + { + ObjectMapper objectMapper = new ObjectMapper(factory); // to not affect shared objectMapper state + objectMapper.setAnnotationIntrospector(new JsonArrayFormat()); + byte[] bytes = objectMapper.writeValueAsBytes(complexPojo); + String scheme = new String(bytes, Charset.forName("UTF-8")); + assertThat(scheme, not(containsString("name"))); // validating schema doesn't contains keys, that's just array + ComplexPojo value = objectMapper.readValue(bytes, ComplexPojo.class); + assertEquals("komamitsu", value.name); + assertEquals(20, value.age); + assertArrayEquals(complexPojo.values.toArray(), value.values.toArray()); + assertEquals(complexPojo.grades.get("math"), value.grades.get("math")); + } } diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java index 1d5156adc..33d7c4fa1 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackDataformatTestBase.java @@ -32,6 +32,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.Collections; public class MessagePackDataformatTestBase { @@ -43,6 +45,7 @@ public class MessagePackDataformatTestBase protected NestedListPojo nestedListPojo; protected NestedListComplexPojo nestedListComplexPojo; protected TinyPojo tinyPojo; + protected ComplexPojo complexPojo; @Before public void setup() @@ -65,14 +68,21 @@ public void setup() nestedListPojo = new NestedListPojo(); nestedListPojo.s = "a string"; - nestedListPojo.strs = Arrays.asList(new String[] {"string", "another string", "another string"}); + nestedListPojo.strs = Arrays.asList("string", "another string", "another string"); tinyPojo = new TinyPojo(); tinyPojo.t = "t string"; + nestedListComplexPojo = new NestedListComplexPojo(); nestedListComplexPojo.s = "a string"; nestedListComplexPojo.foos = new ArrayList(); nestedListComplexPojo.foos.add(tinyPojo); + + complexPojo = new ComplexPojo(); + complexPojo.name = "komamitsu"; + complexPojo.age = 20; + complexPojo.grades = Collections.singletonMap("math", 97); + complexPojo.values = Arrays.asList("one", "two", "three"); } @After @@ -108,6 +118,14 @@ public static class NestedListPojo public List strs; } + public static class ComplexPojo + { + public String name; + public int age; + public List values; + public Map grades; + } + public static class TinyPojo { public String t;