Первоначально написано
Себастьеном Делузом в блоге SpringSource
Поддержка Spring Jackson была улучшена в последнее время, чтобы стать более гибкой и мощной. В этой записи блога содержится обновленная информация о наиболее полезных функциях, связанных с Jackson, доступных в Spring Framework 4.x и Spring Boot. Все примеры кода взяты из этого демонстрационного приложения Spring-Jackson-Demo , не стесняйтесь взглянуть на код.
JSON Views
Иногда бывает полезно отфильтровать контекстуальные объекты, сериализованные в тело ответа HTTP. Чтобы обеспечить такие возможности, Spring MVC теперь имеет встроенную поддержку последовательных представлений Джексона .
В следующем примере показано, как использовать @JsonView для фильтрации полей в зависимости от контекста сериализации — например, получить представление «сводки» при работе с коллекциями и получить полное представление при работе с одним ресурсом:
public class View {
interface Summary {}
}
public class User {
@JsonView(View.Summary.class)
private Long id;
@JsonView(View.Summary.class)
private String firstname;
@JsonView(View.Summary.class)
private String lastname;
private String email;
private String address;
private String postalCode;
private String city;
private String country;
}
public class Message {
@JsonView(View.Summary.class)
private Long id;
@JsonView(View.Summary.class)
private LocalDate created;
@JsonView(View.Summary.class)
private String title;
@JsonView(View.Summary.class)
private User author;
private List<User> recipients;
private String body;
}
Благодаря @JsonView поддержке Spring MVC можно выбрать для каждого метода обработчика, какое поле должно быть сериализовано:
@RestController
public class MessageController {
@Autowired
private MessageService messageService;
@JsonView(View.Summary.class)
@RequestMapping("/")
public List<Message> getAllMessages() {
return messageService.getAll();
}
@RequestMapping("/{id}")
public Message getMessage(@PathVariable Long id) {
return messageService.get(id);
}
}
В этом примере, если все сообщения получены, сериализуются только самые важные поля благодаря getAllMessages() методу, помеченному как @JsonView(View.Summary.class):
[ {
"id" : 1,
"created" : "2014-11-14",
"title" : "Info",
"author" : {
"id" : 1,
"firstname" : "Brian",
"lastname" : "Clozel"
}
}, {
"id" : 2,
"created" : "2014-11-14",
"title" : "Warning",
"author" : {
"id" : 2,
"firstname" : "Stéphane",
"lastname" : "Nicoll"
}
}, {
"id" : 3,
"created" : "2014-11-14",
"title" : "Alert",
"author" : {
"id" : 3,
"firstname" : "Rossen",
"lastname" : "Stoyanchev"
}
} ]
В Spring MVC для конфигурации по умолчанию MapperFeature.DEFAULT_VIEW_INCLUSION установлено значение false. Это означает, что при включении JSON View неаннотированные поля или свойства, такие как body или recipients не сериализуемые.
Когда конкретный объект Message извлекается с использованием getMessage() метода-обработчика (не указан JSON View), все поля сериализуются, как и ожидалось:
{
"id" : 1,
"created" : "2014-11-14",
"title" : "Info",
"body" : "This is an information message",
"author" : {
"id" : 1,
"firstname" : "Brian",
"lastname" : "Clozel",
"email" : "bclozel@pivotal.io",
"address" : "1 Jaures street",
"postalCode" : "69003",
"city" : "Lyon",
"country" : "France"
},
"recipients" : [ {
"id" : 2,
"firstname" : "Stéphane",
"lastname" : "Nicoll",
"email" : "snicoll@pivotal.io",
"address" : "42 Obama street",
"postalCode" : "1000",
"city" : "Brussel",
"country" : "Belgium"
}, {
"id" : 3,
"firstname" : "Rossen",
"lastname" : "Stoyanchev",
"email" : "rstoyanchev@pivotal.io",
"address" : "3 Warren street",
"postalCode" : "10011",
"city" : "New York",
"country" : "USA"
} ]
}
В @JsonView аннотации можно указать только один класс или интерфейс , но вы можете использовать наследование для представления иерархий JSON View (если поле является частью JSON View, оно также будет частью родительского представления). Например, этот метод-обработчик будет сериализовать поля, отмеченные @JsonView(View.Summary.class) и @JsonView(View.SummaryWithRecipients.class):
public class View {
interface Summary {}
interface SummaryWithRecipients extends Summary {}
}
public class Message {
@JsonView(View.Summary.class)
private Long id;
@JsonView(View.Summary.class)
private LocalDate created;
@JsonView(View.Summary.class)
private String title;
@JsonView(View.Summary.class)
private User author;
@JsonView(View.SummaryWithRecipients.class)
private List<User> recipients;
private String body;
}
@RestController
public class MessageController {
@Autowired
private MessageService messageService;
@JsonView(View.SummaryWithRecipients.class)
@RequestMapping("/with-recipients")
public List<Message> getAllMessagesWithRecipients() {
return messageService.getAll();
}
}
Представления JSON также могут быть указаны при использовании RestTemplate HTTP-клиента или MappingJackson2JsonView путем помещения значения для сериализации в, MappingJacksonValue как показано в этом примере кода .
JSONP
Как описано в справочной документации , вы можете включить JSONP для @ResponseBody и ResponseEntity методы, объявив @ControllerAdvice компонент, который расширяется, AbstractJsonpResponseBodyAdvice как показано ниже:
@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice() {
super("callback");
}
}
После регистрации такого @ControllerAdvice компонента будет возможно запросить веб-службу JSON из другого домена с помощью <script /> тега:
<script type="application/javascript"
src="http://mydomain.com/1.json?jsonp=parseResponse">
</script>
В этом примере полученная полезная нагрузка будет:
parseResponse({
"id" : 1,
"created" : "2014-11-14",
...
});
JSONP также поддерживается и автоматически включается при использовании MappingJackson2JsonViewс запросом, у которого есть параметр запроса с именем jsonp или callback. Имена параметров запроса JSONP можно настроить с помощью jsonpParameterNames свойства.
Поддержка XML
Начиная с версии 2.0, Джексон обеспечивает первоклассную поддержку для некоторых других форматов данных, чем JSON. Spring Framework и Spring Boot предоставляют встроенную поддержку сериализации / десериализации XML на основе Jackson.
Как только вы включаете jackson-dataformat-xml зависимость в ваш проект, она автоматически используется вместо JAXB2.
Использование расширения Jackson XML имеет несколько преимуществ перед JAXB2:
- Аннотации Джексона и JAXB признаны
- Поддерживаются JSON View, что позволяет легко создавать веб-сервисы REST с одинаковым фильтрованным выводом для форматов данных XML и JSON.
- Нет необходимости аннотировать ваш класс
@XmlRootElement, каждый класс, сериализуемый в JSON, будет сериализуем в XML
Обычно вы также хотите убедиться, что используемой библиотекой XML является Woodstox, поскольку:
- Это быстрее, чем реализация Stax, предоставляемая JDK
- Это позволяет избежать некоторых известных проблем, таких как добавление ненужных префиксов пространства имен
- Некоторые функции, такие как красивая печать, не работают без нее
Чтобы использовать его, просто добавьте последнюю woodstox-core-asl доступную зависимость для вашего проекта.
Настройка Джексона ObjectMapper
До Spring Framework 4.1.1 Джексон HttpMessageConverterиспользовал ObjectMapper конфигурацию по умолчанию. Чтобы обеспечить лучшую и легко настраиваемую конфигурацию по умолчанию, Jackson2ObjectMapperBuilder была введена новая . Это эквивалент JavaConfig хорошо известного, Jackson2ObjectMapperFactoryBean используемого в конфигурации XML.
Jackson2ObjectMapperBuilder предоставляет приятный API для настройки различных параметров Jackson, сохраняя Spring Framework по умолчанию. Это также позволяет создавать ObjectMapper и XmlMapper экземпляры, основанные на той же конфигурации.
И то, Jackson2ObjectMapperBuilder и другое Jackson2ObjectMapperFactoryBean определяет лучшую конфигурацию Джексона по умолчанию. Например, для DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES свойства установлено значение false, чтобы разрешить десериализацию объектов JSON с несопоставленными свойствами.
Поддержка Джексоном типов данных API даты и времени Java 8 автоматически регистрируется при использовании Java 8 и jackson-datatype-jsr310 находится на пути к классам. Поддержка Joda-Time также регистрируется, когда она jackson-datatype-joda является частью вашего проекта.
Эти классы также позволяют легко регистрировать миксины Джексона , модули , сериализаторы или даже стратегии именования свойств, например, PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES если вы хотите userName преобразовать свое свойство java user_name в JSON.
С весенней загрузкой
Как описано в справочной документации Spring Boot, существуют различные способы настройки Jackson ObjectMapper .
Например , вы можете включить / выключить Джексон особенности легко добавляя свойства , как spring.jackson.serialization.indent_output=true в application.properties.
В качестве альтернативы, в следующей версии 1.2 Spring Boot также позволяет настроить конфигурацию Джексона (JSON и XML), используемую Spring MVC HttpMessageConverter, объявив Jackson2ObjectMapperBuilder @Bean:
@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
return builder;
}
Это полезно, если вы хотите использовать расширенную конфигурацию Джексона, не доступную через обычные ключи конфигурации.
Без весенней загрузки
В простом приложении Spring Framework вы также можете использовать Jackson2ObjectMapperBuilder для настройки XML и JSON, HttpMessageConverterкак показано ниже:
@Configuration
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
}
}
Еще не все
В следующем выпуске Spring Framework 4.1.3 благодаря добавлению контекста Spring HandlerInstantiator (см. SPR-10768 для более подробной информации) вы сможете автоматически связывать обработчики Jackson (сериализаторы, десериализаторы, преобразователи идентификаторов типов и типов).
Это позволит вам создать, например, пользовательский десериализатор, который заменит поле, содержащее только ссылку в полезной нагрузке JSON, на полное, Entity извлеченное из базы данных.