property jsonproperty annotation java json serialization jackson

jsonproperty - json annotation java



Serialización personalizada Jackson JSON para ciertos campos (5)

¿Hay alguna manera de usar Jackson JSON Processor para hacer una serialización personalizada a nivel de campo? Por ejemplo, me gustaría tener la clase

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

serializado al siguiente JSON:

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

Tenga en cuenta que age = 25 está codificado como un número, mientras que favoriteNumber = 123 está codificado como una cadena . Fuera de la caja, Jackson llama a un número. En este caso, quiero que favoriteNumber se codifique como una cadena.


Agregue un @JsonProperty anotado @JsonProperty , que devuelve un String , para el campo favoriteNumber :

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"} } }


Jackson-databind (al menos 2.1.3) proporciona ToStringSerializer especial ( com.fasterxml.jackson.databind.ser.std.ToStringSerializer )

Ejemplo:

public class Person { public String name; public int age; @JsonSerialize(using = ToStringSerializer.class) public int favoriteNumber: }


Puede implementar un serializador personalizado de la siguiente manera:

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 debe manejar el autoboxing de int a Integer por usted.


con la ayuda de @JsonView podemos decidir campos de clases de modelos para serializar que satisfagan los criterios mínimos (tenemos que definir los criterios) como que podemos tener una clase central con 10 propiedades, pero solo se pueden serializar 5 propiedades que son necesarias para el cliente solamente

Defina nuestras Vistas simplemente creando la siguiente clase:

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

Clase modelo anotada con vistas:

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 ... .. }

Ahora tenemos que escribir el convertidor json personalizado simplemente extendiendo la clase HttpMessageConverter desde la primavera como:

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); } } }

Ahora hay que decirle a la primavera que use esta conversión JSON personalizada simplemente colocando esto en 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>

Así es como podrá decidir qué campos se serializarán.


jackson-annotations proporciona @JsonFormat que puede manejar muchas personalizaciones sin la necesidad de escribir el serializador personalizado.

Por ejemplo, al solicitar una forma STRING para un campo con tipo numérico, se generará el valor numérico como cadena

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

dará como resultado la salida deseada

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