【问题标题】:Use spring's objectmapper with kotlin fuel将 spring 的 objectmapper 与 kotlinfuel 一起使用
【发布时间】:2018-12-14 10:43:33
【问题描述】:

我在我的 kotlin spring 应用程序中使用燃料进行 http 集成,有一种方法可以使用 Jackson 进行 JSON 序列化/反序列化。 但是映射器是 FuelJackson.kt 中的一个 val。 有没有办法用定义为 bean 的 Spring 配置的 Jackson Objectmapper 来覆盖它?

【问题讨论】:

    标签: spring kotlin kotlin-fuel


    【解决方案1】:

    有一个类接受 spring 初始化的 jackson objectmapper:

    class FuelDeserializer(val objectMapper: ObjectMapper) {
    inline fun <reified T : Any> deserialize() = object : ResponseDeserializable<T> 
    {
            override fun deserialize(inputStream: InputStream): T? {
                return objectMapper.readValue(inputStream)
            }
    
            override fun deserialize(reader: Reader): T? {
                return objectMapper.readValue(reader)
            }
    
            override fun deserialize(bytes: ByteArray): T? {
                return objectMapper.readValue(bytes)
            }
    
            override fun deserialize(content: String): T? {
                return objectMapper.readValue(content)
            }
        }
    }
    

    这个类可以作为一个bean添加到你的配置中

    @Configuration
    class ObjectMapperConfiguration {
        @Bean
        fun objectMapper(builder: Jackson2ObjectMapperBuilder): ObjectMapper {
            val objectMapper = builder.build<ObjectMapper>()
            objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
            objectMapper.findAndRegisterModules()
            return objectMapper
        }
    
        @Bean
        fun fuelDeserializer(objectMapper: ObjectMapper): FuelDeserializer {
            return FuelDeserializer(objectMapper)
        }
    }
    

    那么用法是这样的

    @Controller
    class PdfGeneratorApi( 
        val fuelDeserializer: FuelDeserializer
    ) {
    
        fun postSomething(): ResponseEntity<?> {
            "http://exampl.com"
                .httpPost()
                .body("Something to post")
                .responseObject<MyObject>(fuelDeserializer.deserialize()) {_, _, result -> 
                when (result) {
                    is Result.Failure -> logger.warn(result.getException()) { "Failure while posting" }
                    is Result.Success -> ResponseEntity.ok(result.get())
                }
           }
        }
    

    【讨论】:

      【解决方案2】:

      FuelJackson.kt 中的 defaultMapper 是一个 val,但这并不意味着你不能向它注册模块。

      您可以在配置类中执行类似的操作。

      @Configuration
      public class JacksonConfiguration {
      
        @Bean
        /**
         * Single place to get object mapper specific modules registered.
         *
         * @return ObjectMapper with necessary modules registered
         */
        public ObjectMapper jacksonObjectMapper() {
          var mapper = new ObjectMapper();
          mapper.registerModule(new Jdk8Module());
          mapper.registerModule(new JavaTimeModule());
          mapper.registerModule(new KotlinModule());
          mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
      
          // it won't be the exact same object mapper used throughout 
          // your spring application, but you can make the fuel mapper 
          // match right here in the bean. 
          FuelJacksonKt.getDefaultMapper().registerModule(new JavaTimeModule());
      
          return mapper;
        }
      }
      

      我完全明白,这并不能为人们提供他们可能想要的所有控制权,但它确实有效,并且它使您不必将 bean 自动连接到您使用燃料的每个地方。

      【讨论】:

      • 很高兴知道,但我想重用 Spring 中已经配置的 ObjectMapper。为每个 ObjectMapper 实例注册模块并不是很可重用。
      • @TomdeVroomen 其实这就是我的意思。我有一个带有 ObjectMapper bean 的杰克逊配置类。在那个 bean 中,我修改了燃料使用的全局映射器以匹配 bean。在这里,我将进行编辑。
      • 啊,太好了!我能预见的唯一问题是当上下文中配置了多个 ObjectMapper bean 时,可能不清楚哪个是 Fuel 的 defaultMapper
      猜你喜欢
      • 2019-11-09
      • 2017-02-18
      • 2014-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-30
      • 2017-05-01
      • 2015-07-15
      • 1970-01-01
      相关资源
      最近更新 更多