2015-02-04 3 views
45

Я использую Spring пыльник (1.2.1), таким же образом, как и в их Building a RESTful Web Service учебнике:Как настроить Jackson JSON mapper, неявно используемый Spring Boot?

@RestController 
public class EventController { 

    @RequestMapping("/events/all") 
    EventList events() { 
     return proxyService.getAllEvents(); 
    } 

} 

Так выше, Spring MVC неявно использует Джексон serialising моего EventList объекта в JSON.

Но я хочу сделать несколько простых настроек в формат JSON, например:

setSerializationInclusion(JsonInclude.Include.NON_NULL) 

Вопрос, , что это самый простой способ настроить неявное JSON картографа?

Я попробовал подход в this blog post, создавая CustomObjectMapper и так далее, но шаг 3, «Регистрация классов в контексте Spring», не удается:

org.springframework.beans.factory.BeanCreationException: 
    Error creating bean with name 'jacksonFix': Injection of autowired dependencies failed; 
    nested exception is org.springframework.beans.factory.BeanCreationException: 
    Could not autowire method: public void com.acme.project.JacksonFix.setAnnotationMethodHandlerAdapter(org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter); 
    nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
    No qualifying bean of type [org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter] 
    found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} 

Похоже, эти инструкции для старых версий Spring MVC, в то время как я ищу простой способ получить эту работу с последней версией Spring Boot.

+0

У вас есть это аннотацию вставленный ?: @SuppressWarnings ({ "SpringJavaAutowiringInspection"}) –

ответ

61

Если вы используете Spring бутсу 1.3, вы можете настроить включение сериализации с помощью application.properties:

spring.jackson.serialization-inclusion=non_null 

После изменений в Джексон 2.7, Spring Загрузочный 1.4 использует свойство с именем spring.jackson.default-property-inclusion вместо:

spring.jackson.default-property-inclusion=non_null 

См. Раздел «Customize the Jackson ObjectMapper» в документации весенней загрузки.

Если вы используете более раннюю версию Spring Boot, самый простой способ настроить включение сериализации в Spring Boot - объявить свой собственный, соответствующим образом сконфигурированный bean-компонент Jackson2ObjectMapperBuilder. Например:

@Bean 
public Jackson2ObjectMapperBuilder objectMapperBuilder() { 
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); 
    builder.serializationInclusion(JsonInclude.Include.NON_NULL); 
    return builder; 
} 
+1

Хорошо, это работает. Где бы вы поместили такой метод? Возможно, в основном классе Application (с '@ ComponentScan',' @ EnableAutoConfiguration' и т. Д.)? – Jonik

+2

Да. Этот метод может использоваться в любом классе '@ Configuration' в вашем приложении. Основной класс «Приложение» - хорошее место для него. –

+2

Важное примечание: класс Jackson2ObjectMapperBuilder является частью компонента spring-web и был добавлен в версию 4.1.1. – gaoagong

9

The documentation указывает несколько способов сделать это.

Если вы хотите полностью заменить по умолчанию ObjectMapper, определить @Bean этого типа и пометить его как @Primary.

Определение @Bean типа Jackson2ObjectMapperBuilder позволит вам настроить как по умолчанию ObjectMapper и XmlMapper (используется в MappingJackson2HttpMessageConverter и MappingJackson2XmlHttpMessageConverter соответственно).

1

Я наткнулся на другое решение, которое довольно приятно.

В основном, только step 2 from the blog posted mentioned и определить пользовательский ObjectMapper как весна @Component. (Вещи начали работать, когда я только удалена всех AnnotationMethodHandlerAdapter материала, начиная с шага 3.)

@Component 
@Primary 
public class CustomObjectMapper extends ObjectMapper { 
    public CustomObjectMapper() { 
     setSerializationInclusion(JsonInclude.Include.NON_NULL); 
     configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
    } 
} 

работает до тех пор, как компонент в пакете сканируемого Spring.(Использование @Primary не является обязательным в моем случае, но почему бы не сделать вещи явно.)

Для меня есть два преимущества по сравнению с другим подходом:

  • Это проще; Я могу просто расширить класс от Jackson и не нуждаться в том, чтобы знать о специфичных для Spring материалах, таких как Jackson2ObjectMapperBuilder.
  • Я хочу использовать те же настройки Jackson для десериализации JSON в другой части моего приложения, и таким образом это очень просто: new CustomObjectMapper() вместо new ObjectMapper().
+0

Недостатком этого подхода является то, что ваша пользовательская конфигурация не будет применяется к любым экземплярам ObjectMapper, которые создаются или настраиваются Spring Boot. –

+0

Хм, пользовательская конфигурация * * используется для неявной сериализации в классах '@ RestController', которые мне в настоящее время достаточно. (Значит, вы имеете в виду, что эти экземпляры создаются Spring MVC, а не Spring Boot?) Но если я столкнусь с другими случаями, когда ObjectMappers нужно создать, я буду учитывать подход Jackson2ObjectMapperBuilder! – Jonik

12

Я отвечаю немного позже на этот вопрос, но кто-то в будущем может найти это полезным. Такой подход, помимо множества других подходов, работает лучше всего, и я лично думаю, что это лучше подходит для веб-приложения.

@Configuration 
@EnableWebMvc 
public class WebConfiguration extends WebMvcConfigurerAdapter { 

... other configurations 

@Override 
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 
     Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); 
     builder.serializationInclusion(JsonInclude.Include.NON_NULL); 
     builder.propertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); 
     builder.serializationInclusion(Include.NON_EMPTY); 
     builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd")); 
     converters.add(new MappingJackson2HttpMessageConverter(builder.build())); 
     converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build())); 
    } 
} 
13

Многие вещи могут быть сконфигурированы в applicationproperties. К сожалению, эта функция только в версии 1.3, но вы можете добавить в Config-Class

@Autowired(required = true) 
public void configeJackson(ObjectMapper jackson2ObjectMapper) { 
    jackson2ObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 
} 

[UPDATE:. Вы должны работать на ObjectMapper, потому что build() -метод вызывается до конфигурации является пробеги]

+0

Это было решение, которое спасло мой день. За исключением того, что я добавил этот метод к самому контроллеру REST, а не к классу конфигурации. –

0

я нашел решение, описанное выше:

spring.jackson.serialization-включения = non_null

работать только начиная с версии 1.4.0.RELEASE из SPR загрузки. Во всех остальных случаях config игнорируется.

Я проверил это, экспериментируя с модификацией пружинной загрузки образца «весна-загрузки образца-Джерси»

7

spring.jackson.serialization-inclusion=non_null имел обыкновение работать для нас

Но когда мы модернизировали пружины загрузочную версию 1.4. 2.RELEASE или выше, он прекратил работать.

Теперь, другая собственность spring.jackson.default-property-inclusion=non_null делает магию.

Фактически, serialization-inclusion устарел. Это то, что мой intellij бросает на меня.

DEPRECATED: ObjectMapper.setSerializationInclusion осуждался в Джексон 2.7

Итак, начать использовать spring.jackson.default-property-inclusion=non_null вместо

0

Я знаю, что вопрос с просьбой к Весеннее ботинке, но я считаю, много людей ища, как это сделать в незагруженной загрузке, например, я ищу почти весь день.

Выше весны 4 нет необходимости настраивать MappingJacksonHttpMessageConverter, если вы только собираетесь настроить ObjectMapper.

Вам просто нужно сделать:

public class MyObjectMapper extends ObjectMapper { 

    private static final long serialVersionUID = 4219938065516862637L; 

    public MyObjectMapper() { 
     super(); 
     enable(SerializationFeature.INDENT_OUTPUT); 
    }  
} 

И в конфигурации Spring, создать этот компонент:

@Bean 
public MyObjectMapper myObjectMapper() {   
    return new MyObjectMapper(); 
}