Special Jackson JSON serialization for specific fields

Is there a way to use the Jackson JSON Processor to perform custom field level serialization? For example, I would like to have a class

public class Person { public String name; public int age; public int favoriteNumber; } 

serialized for the following JSON:

 { "name": "Joe", "age": 25, "favoriteNumber": "123" } 

Note that age = 25 is encoded as a number , and favoriteNumber = 123 is encoded as a string . Out of the box Jackson marshalls int to number. In this case, I want favoriteNumber to be encoded as a string.

+78
java json jackson serialization
Aug 20 2018-12-12T00:
source share
7 answers

You can implement your own serializer as follows:

 public class Person { public String name; public int age; @JsonSerialize(using = IntToStringSerializer.class, as=String.class) public int favoriteNumber: } public class IntToStringSerializer extends JsonSerializer<Integer> { @Override public void serialize(Integer tmpInt, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { jsonGenerator.writeObject(tmpInt.toString()); } } 

Java should handle autoboxing from int to Integer for you.

+87
Aug 21 2018-12-12T00:
source share

Jackson-databind (at least 2.1.3) provides special ToStringSerializer ( com.fasterxml.jackson.databind.ser.std.ToStringSerializer )

Example:

 public class Person { public String name; public int age; @JsonSerialize(using = ToStringSerializer.class) public int favoriteNumber: } 
+46
Feb 14 '13 at 11:24
source share

Add the annotated getter @JsonProperty , which returns a String for the favoriteNumber field:

 public class Person { public String name; public int age; private int favoriteNumber; public Person(String name, int age, int favoriteNumber) { this.name = name; this.age = age; this.favoriteNumber = favoriteNumber; } @JsonProperty public String getFavoriteNumber() { return String.valueOf(favoriteNumber); } public static void main(String... args) throws Exception { Person p = new Person("Joe", 25, 123); ObjectMapper mapper = new ObjectMapper(); System.out.println(mapper.writeValueAsString(p)); // {"name":"Joe","age":25,"favoriteNumber":"123"} } } 
+10
Aug 21 2018-12-12T00:
source share

jackson-annotations provides @JsonFormat , which can handle many settings without having to write its own serializer.

For example, a query of the form STRING for a field with a numeric type displays a numeric value as a string

 public class Person { public String name; public int age; @JsonFormat(shape = JsonFormat.Shape.STRING) public int favoriteNumber; } 

will lead to the desired result

 {"name":"Joe","age":25,"favoriteNumber":"123"} 
+6
Aug 15 '17 at 13:51 on
source share

using @JsonView we can define model class fields for serialization that satisfy the minimum criteria (we must define criteria), since we can have one main class with 10 properties, but only 5 properties can be serialized, which are necessary only for the client

Define our views by simply creating the following class:

 public class Views { static class Android{}; static class IOS{}; static class Web{}; } 

Annotated model class with views:

 public class Demo { public Demo() { } @JsonView(Views.IOS.class) private String iosField; @JsonView(Views.Android.class) private String androidField; @JsonView(Views.Web.class) private String webField; // getters/setters ... .. } 

Now we need to write our own json converter by simply extending the HttpMessageConverter class from spring as:

  public class CustomJacksonConverter implements HttpMessageConverter<Object> { public CustomJacksonConverter() { super(); //this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.ClientView.class)); this.delegate.getObjectMapper().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true); this.delegate.getObjectMapper().setSerializationInclusion(Include.NON_NULL); } // a real message converter that will respond to methods and do the actual work private MappingJackson2HttpMessageConverter delegate = new MappingJackson2HttpMessageConverter(); @Override public boolean canRead(Class<?> clazz, MediaType mediaType) { return delegate.canRead(clazz, mediaType); } @Override public boolean canWrite(Class<?> clazz, MediaType mediaType) { return delegate.canWrite(clazz, mediaType); } @Override public List<MediaType> getSupportedMediaTypes() { return delegate.getSupportedMediaTypes(); } @Override public Object read(Class<? extends Object> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { return delegate.read(clazz, inputMessage); } @Override public void write(Object obj, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { synchronized(this) { String userAgent = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("userAgent"); if ( userAgent != null ) { switch (userAgent) { case "IOS" : this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.IOS.class)); break; case "Android" : this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.Android.class)); break; case "Web" : this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( Views.Web.class)); break; default: this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( null )); break; } } else { // reset to default view this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( null )); } delegate.write(obj, contentType, outputMessage); } } } 

Now you need to tell spring to use this custom json converter by simply placing it in dispatcher-servlet.xml

 <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean id="jsonConverter" class="com.mactores.org.CustomJacksonConverter" > </bean> </mvc:message-converters> </mvc:annotation-driven> 

How you can decide which fields to serialize.

+2
Jul 12 '16 at 6:25
source share

we used custom serialization, but now I can no longer use POJO, as more and more customers will get access to our leisure service. how can i still serialize certain fields? just posted this question Custom attribute based serialization in JSON

0
Jan 23 '19 at 17:16
source share

If you do not want to pollute your model with annotations and want to perform some custom operations, you can use mixins.

 ObjectMapper mapper = new ObjectMapper(); SimpleModule simpleModule = new SimpleModule(); simpleModule.setMixInAnnotation(Person.class, PersonMixin.class); mapper.registerModule(simpleModule); 

Cancel age:

 public abstract class PersonMixin { @JsonSerialize(using = PersonAgeSerializer.class) public String age; } 

Do everything you need with age:

 public class PersonAgeSerializer extends JsonSerializer<Integer> { @Override public void serialize(Integer integer, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeString(String.valueOf(integer * 52) + " months"); } } 
0
Apr 05 '19 at 9:34 am
source share



All Articles