Skip to content

Instantly share code, notes, and snippets.

@theotherian
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theotherian/9285448 to your computer and use it in GitHub Desktop.
Save theotherian/9285448 to your computer and use it in GitHub Desktop.
Using Jackson Mixins and Modules to fix serialization problems
Using Jackson Mixins and Modules to fix serialization problems
private User createUser() {
User user = new User();
user.setName("me");
Thing thing = new Thing();
thing.setName("that");
thing.setUser(user);
user.setThings(Lists.newArrayList(thing));
return user;
}
private Widget createWidget() {
Widget widget = new Widget();
widget.setId(1);
WidgetName name = new WidgetName();
name.value("my widget");
widget.setName(name);
return widget;
}
package com.theotherian.jackson;
import java.io.StringWriter;
import org.junit.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.theotherian.jackson.dto.Widget;
import com.theotherian.jackson.dto.WidgetName;
public class ModuleTest {
@Test
public void failureWithoutProperty() throws Exception {
Widget widget = createWidget();
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
StringWriter writer = new StringWriter();
mapper.writeValue(writer, widget);
System.out.println(writer.toString());
}
}
package com.theotherian.jackson;
import java.io.StringWriter;
import org.junit.Test;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.theotherian.jackson.dto.Widget;
import com.theotherian.jackson.dto.WidgetName;
import com.theotherian.jackson.serializer.WidgetNameSerializer;
public class ModuleSuccessTest {
@Test
public void success() throws Exception {
Widget widget = createWidget();
ObjectMapper mapper = new ObjectMapper();
Module serializerModule = new SimpleModule().addSerializer(WidgetName.class, new WidgetNameSerializer());
mapper.registerModule(serializerModule);
StringWriter writer = new StringWriter();
mapper.writeValue(writer, widget);
System.out.println(writer.toString());
}
}
package com.theotherian.jackson;
import java.io.StringWriter;
import org.junit.Test;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.theotherian.jackson.dto.Widget;
import com.theotherian.jackson.dto.WidgetName;
import com.theotherian.jackson.serializer.WidgetNameSerializer;
public class ModuleTest {
@Test
public void failureWithException() throws Exception {
Widget widget = createWidget();
ObjectMapper mapper = new ObjectMapper();
StringWriter writer = new StringWriter();
mapper.writeValue(writer, widget);
System.out.println(writer.toString());
}
@Test
public void failureWithoutProperty() throws Exception {
Widget widget = createWidget();
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
StringWriter writer = new StringWriter();
mapper.writeValue(writer, widget);
System.out.println(writer.toString());
}
@Test
public void success() throws Exception {
Widget widget = createWidget();
ObjectMapper mapper = new ObjectMapper();
Module serializerModule = new SimpleModule().addSerializer(WidgetName.class, new WidgetNameSerializer());
mapper.registerModule(serializerModule);
StringWriter writer = new StringWriter();
mapper.writeValue(writer, widget);
System.out.println(writer.toString());
}
private Widget createWidget() {
Widget widget = new Widget();
widget.setId(1);
WidgetName name = new WidgetName();
name.value("my widget");
widget.setName(name);
return widget;
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.theotherian.jackson</groupId>
<artifactId>jackson-mixins-and-modules</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>jackson-mixins-and-modules</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>16.0</version>
</dependency>
</dependencies>
</project>
com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.theotherian.jackson.dto.User["things"]->java.util.ArrayList[0]->com.theotherian.jackson.dto.Thing["user"]->...
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:646)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:541)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:632)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
...
Caused by: java.lang.StackOverflowError
...
import java.io.StringWriter;
import org.junit.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.theotherian.jackson.dto.User;
public class SerializationFailureTest {
@Test
public void failure() throws Exception {
User user = createUser();
ObjectMapper mapper = new ObjectMapper();
StringWriter writer = new StringWriter();
mapper.writeValue(writer, user);
}
}
package com.theotherian.jackson;
import java.io.StringWriter;
import org.junit.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.google.common.collect.Lists;
import com.theotherian.jackson.dto.Thing;
import com.theotherian.jackson.dto.User;
import com.theotherian.jackson.mixin.ThingMixin;
public class SerializationSuccessTest {
@Test
public void success() throws Exception {
User user = createUser();
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Thing.class, ThingMixin.class);
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("thing filter", SimpleBeanPropertyFilter.serializeAllExcept("user"));
mapper.setFilters(filterProvider);
StringWriter writer = new StringWriter();
mapper.writeValue(writer, user);
}
}
package com.theotherian.jackson;
import java.io.StringWriter;
import org.junit.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.google.common.collect.Lists;
import com.theotherian.jackson.dto.Thing;
import com.theotherian.jackson.dto.User;
import com.theotherian.jackson.mixin.ThingMixin;
public class SerializationTest {
@Test
public void failure() throws Exception {
User user = createUser();
ObjectMapper mapper = new ObjectMapper();
StringWriter writer = new StringWriter();
mapper.writeValue(writer, user);
}
@Test
public void success() throws Exception {
User user = createUser();
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Thing.class, ThingMixin.class);
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("thing filter", SimpleBeanPropertyFilter.serializeAllExcept("user"));
mapper.setFilters(filterProvider);
StringWriter writer = new StringWriter();
mapper.writeValue(writer, user);
}
private User createUser() {
User user = new User();
user.setName("me");
Thing thing = new Thing();
thing.setName("that");
thing.setUser(user);
user.setThings(Lists.newArrayList(thing));
return user;
}
}
{"id":1,"name":"my widget"}
package com.theotherian.jackson.dto;
public class Thing {
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
private User user;
public User getUser() { return user; }
public void setUser(User user) { this.user = user; }
}
package com.theotherian.jackson.mixin;
import com.fasterxml.jackson.annotation.JsonFilter;
@JsonFilter("thing filter")
public class ThingMixin {
}
package com.theotherian.jackson.dto;
import java.util.List;
public class User {
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
private List<Thing> things;
public List<Thing> getThings() { return things; }
public void setThings(List<Thing> things) { this.things = things; }
}
package com.theotherian.jackson.dto;
public class Widget {
private long id;
public long getId() { return id; }
public void setId(long id) { this.id = id; }
private WidgetName name;
public WidgetName getName() { return name; }
public void setName(WidgetName name) { this.name = name; }
}
package com.theotherian.jackson.dto;
public class WidgetName {
private String value;
public String value() { return value; }
public void value(String value) { this.value = value; }
}
package com.theotherian.jackson.serializer;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.theotherian.jackson.dto.WidgetName;
public class WidgetNameSerializer extends JsonSerializer<WidgetName> {
@Override
public void serialize(WidgetName widgetName, JsonGenerator jgen, SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeString(widgetName.value());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment