簡體   English   中英

無法在 Spring Boot 中將 ProblemHandler 設置為 ObjectMapper

[英]Can't set ProblemHandler to ObjectMapper in Spring Boot

我嘗試使用 Jackson2ObjectMapperBuilderCustomizer 將自定義問題處理程序添加到對象映射器:

@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
    return new Jackson2ObjectMapperBuilderCustomizer() {
        @Override
        public void customize(Jackson2ObjectMapperBuilder builder) {
            ObjectMapper m = builder.build();
            m.addHandler(
                    new DeserializationProblemHandler() {
                        @Override
                        public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p, JsonDeserializer<?> deserializer, Object beanOrClass, String propertyName) throws IOException {
                            System.out.println("ahahahaa");
                            return super.handleUnknownProperty(ctxt, p, deserializer, beanOrClass, propertyName);
                        }
                    }
            );
        }
    };
}

但是當我自動裝配 ObjectMapper bean _problemHandlers 屬性為空時。

我還嘗試使用以下方法自定義現有的 ObjectMapper:

@Autowired
public customize(ObjectMapper mapper) {
...
}

但結果是一樣的。 我不知道誰能刪除這個屬性。 我根本不會在另一個地方初始化對象映射器的另一個構建器/工廠/等。 我做錯了什么?

無法通過Jackson2ObjectMapperBuilderJackson2ObjectMapperBuilderCustomizer直接將DeserializationProblemHandler添加到ObjectMapper 在構建器上調用build()是不行的,因為生成的ObjectMapper是該方法的本地:Spring 本身稍后會調用build() ,創建另一個ObjectMapper實例。

但是,可以通過注冊 Jackson 模塊來做到這一點:

  • 構建器有一個modules()方法
  • 模塊可以通過setupModule()訪問SetupContext實例,該實例具有addDeserializationProblemHandler()方法

這應該可以工作

@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
    return new Jackson2ObjectMapperBuilderCustomizer() {
        @Override
        public void customize(Jackson2ObjectMapperBuilder builder) {
            builder.modules(new MyModule());
        }
    };
}

private static class MyModule extends SimpleModule {
    @Override
    public void setupModule(SetupContext context) {
        // Required, as documented in the Javadoc of SimpleModule
        super.setupModule(context);
        context.addDeserializationProblemHandler(new MyDeserializationProblemHandler());
    } 
}

private static class MyDeserializationProblemHandler extends DeserializationProblemHandler {
    @Override
    public boolean handleUnknownProperty(DeserializationContext ctxt,
                                         JsonParser p,
                                         JsonDeserializer<?> deserializer,
                                         Object beanOrClass,
                                         String propertyName)
            throws IOException {
        System.out.println("ahahahaa");
        return super.handleUnknownProperty(ctxt, p, deserializer, beanOrClass, propertyName);
    }
}

編輯 (2022-06-27)

正如 E-Riz 在評論中提到的,對於較新的 Spring Boot 版本,您只需將模塊注冊為 Spring Bean,它將在ObjectMapper上與所有其他模塊一起配置。

// Or declare it as a @Bean in a @Configuration
@Component
public class MyModule extends SimpleModule {
    @Override
    public void setupModule(SetupContext context) {
        // Required, as documented in the Javadoc of SimpleModule
        super.setupModule(context);
        context.addDeserializationProblemHandler(new MyDeserializationProblemHandler());
    } 

    private static class MyDeserializationProblemHandler extends DeserializationProblemHandler {
        @Override
        public boolean handleUnknownProperty(DeserializationContext ctxt,
                                             JsonParser p,
                                             JsonDeserializer<?> deserializer,
                                             Object beanOrClass,
                                             String propertyName)
                throws IOException {
            System.out.println("ahahahaa");
            return super.handleUnknownProperty(ctxt, p, deserializer, beanOrClass, propertyName);
        }
    }
}

我是Spring Boot的新手,因此很難理解如何使用它。 但經過一番研究,我設法弄清楚了。

我必須創建一個名為src.main.java.com.applicationname.config.JacksonUnknownPropertyConfig.java的類,其內容為:

package com.applicationname.config;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.server.ResponseStatusException;

import java.io.IOException;

@SpringBootConfiguration
public class JacksonUnknownPropertyConfig {
  private static final Logger logger = LoggerFactory.getLogger(JacksonUnknownPropertyConfig.class);

  @Bean
  public Jackson2ObjectMapperBuilderCustomizer customizer() {
    return new Jackson2ObjectMapperBuilderCustomizer() {
      @Override
      public void customize(Jackson2ObjectMapperBuilder builder) {
        builder.modules(new MyModule());
      }
    };
  }

  private static class MyModule extends SimpleModule {
    @Override
    public void setupModule(SetupContext context) {
      // Required, as documented in the Javadoc of SimpleModule
      super.setupModule(context);
      context.addDeserializationProblemHandler(new MyDeserializationProblemHandler());
    }
  }

  private static class MyDeserializationProblemHandler extends DeserializationProblemHandler {
    @Override
    public boolean handleUnknownProperty(
        DeserializationContext ctxt,
        JsonParser p,
        JsonDeserializer<?> deserializer,
        Object beanOrClass,
        String propertyName)
        throws IOException {

      System.out.println("ahahahaa");

      final String missing = String.format("Unknown request property '%s'", propertyName);
      logger.warn(missing);

      if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, missing);
      }
      return super.handleUnknownProperty(ctxt, p, deserializer, beanOrClass, propertyName);
    }
  }
}

而且我還必須將FAIL_ON_UNKNOWN_PROPERTIES添加到文件src.main.resources.application.properties

spring.jackson.deserialization.FAIL_ON_UNKNOWN_PROPERTIES=true

在此之后,看起來Sprint Boot會自動識別我創建的新類並正確加載它。

2020-07-20 23:41:22.934  INFO 16684 --- [         task-1] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-07-20 23:41:22.944 TRACE 16684 --- [         task-1] o.h.type.spi.TypeConfiguration$Scope     : Handling #sessionFactoryCreated from [org.hibernate.internal.SessionFactoryImpl@3edd0926] for TypeConfiguration
2020-07-20 23:41:22.946  INFO 16684 --- [         task-1] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-07-20 23:41:23.209  INFO 16684 --- [           main] DeferredRepositoryInitializationListener : Spring Data repositories initialized!
2020-07-20 23:41:23.222  INFO 16684 --- [           main] c.a.p.AppointmentPublishingApplication   : Started AppointmentPublishingApplication in 6.445 seconds (JVM running for 7.615)
2020-07-20 23:41:26.229  INFO 16684 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-07-20 23:41:26.229  INFO 16684 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2020-07-20 23:41:26.236  INFO 16684 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 7 ms
ahahahaa

相關話題:

  1. Spring Boot,Spring MVC JSON RequestBody:未知屬性被忽略
  2. 如何在 Spring Boot 1.4 中自定義 Jackson
  3. 傑克遜無法識別的字段
  4. 使用 Jackson 忽略 JSON 對象上的新字段
  5. 在 Controller 中為每個 RequestMapping 配置不同的 FAIL_ON_UNKNOWN_PROPERTIES
  6. 傑克遜解串器優先級?
  7. Spring Data Elastic - Java.Time.Instant 類傑克遜反序列化不起作用
  8. 啟用 Jackson 將空對象反序列化為 Null
  9. Spring RestController:拒絕帶有未知字段的請求
  10. 您如何全局設置 Jackson 以忽略 Spring 中的未知屬性?
  11. https://www.baeldung.com/spring-bean
  12. https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-spring-mvc

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM