Джексон JSON пользовательская сериализация для определенных полей
есть ли способ использовать процессор Jackson JSON для сериализации пользовательского уровня поля? Например, я хотел бы иметь класс
public class Person {
public String name;
public int age;
public int favoriteNumber;
}
сериализуется в следующий JSON:
{ "name": "Joe", "age": 25, "favoriteNumber": "123" }
обратите внимание, что возраст=25 кодируется как в то время как favoriteNumber=123 кодируется как строка. Из коробки Джексон маршаллс int
в число. В этом случае я хочу, чтобы favoriteNumber был закодирован как строка.
5 ответов:
вы можете реализовать пользовательский сериализатор следующим образом:
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 должен обрабатывать автобоксинг от
int
toInteger
для вас.
Jackson-databind (по крайней мере 2.1.3) предоставляет специальные
ToStringSerializer
(com.fasterxml.jackson.databind.ser.std.ToStringSerializer
)пример:
public class Person { public String name; public int age; @JsonSerialize(using = ToStringSerializer.class) public int favoriteNumber: }
Джексон-аннотации предоставляет
@JsonFormat
который может обрабатывать множество настроек без необходимости писать пользовательский сериализатор.например, запрос
STRING
форма для поля с числовым типом выведет числовое значение в виде строкиpublic class Person { public String name; public int age; @JsonFormat(shape = JsonFormat.Shape.STRING) public int favoriteNumber; }
приведет к желаемому результату
{"name":"Joe","age":25,"favoriteNumber":"123"}
С помощью @JsonView мы можем решить поля классов моделей для сериализации, которые удовлетворяют минимальным критериям (мы должны определить критерии), как мы можем иметь один основной класс с 10 свойствами, но только 5 свойств могут быть сериализованы, которые необходимы только для клиента
определите наши взгляды, просто создав следующий класс:
public class Views { static class Android{}; static class IOS{}; static class Web{}; }
аннотированный класс модели с представлениями:
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 ... .. }
теперь мы должны написать пользовательский конвертер json просто расширяя класс HttpMessageConverter от spring как:
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); } } }
теперь нужно сказать spring, чтобы использовать это пользовательское преобразование json, просто поместив это в 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>
вот как вы сможете решить, какие поля для сериализации.