配置 Dropwizard ObjectMapper 以配置忽略未知

Posted

技术标签:

【中文标题】配置 Dropwizard ObjectMapper 以配置忽略未知【英文标题】:Configure Dropwizard ObjectMapper for configuration to ignore unknown 【发布时间】:2018-05-20 10:29:41 【问题描述】:

使用ObjectMapper (com.fasterxml.jackson.databind) 可以指定它应该忽略未知属性。这可以通过在类级别添加@JsonIgnoreProperties(ignoreUnknown = true) 或通过将其设置为映射器中的默认行为来完成。但是,在Application<MyConfiguration>initialize() 方法中执行此操作时,似乎没有效果。

ObjectMapper mapper = bootstrap.getObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

对于配置文件中的未知属性,它仍然失败。如何配置 Dropwizard 以忽略未知属性?

【问题讨论】:

DW的版本是多少? 我的版本是0.7.1。显然,较新的版本具有更多实际配置 ModelMapper 的能力,但无论之前的配置是什么,此版本都会在 FAIL_ON_UNKNOWN_PROPERTIES 上强制使用 true 标志。 【参考方案1】:

您需要通过以下方式禁用该功能:

bootstrap.getObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

更新:该功能禁用适用于 API 资源,但不适用于配置 YAML。相反,您需要将下面的注释(与问题中提到的相同)添加到配置类中:

@JsonIgnoreProperties(ignoreUnknown = true)

【讨论】:

不,不幸的是,这不起作用。我尝试(1)只禁用和(2)先禁用然后将其配置为false,但都给了我错误:* Unrecognized field at: blabla Did you mean?: ... 我还可以在这里补充一点,我使用的 Dropwizard 版本 (0.7.1) 显然会在 ModelMapper 上强制执行 true 标志,无论您将配置设置为什么。 @Myone 我刚刚测试了在 DW 0.7.1 中禁用此功能,它对我有用。我为此创建了一个简单的应用程序:github.com/andremanuelbarbosa/SOQ47676034 我已经在本地检查了您的代码,虽然禁用该功能不会给您任何错误,但由于我的回答中描述的原因,它也不会产生任何影响。您可以通过将unknown: true 添加到conf.yml 来进行测试,这会导致Myone 提到的错误。 对,这与ConfigurationFactory 在启用FAIL_ON_UNKNOWN_PROPERTIES 之前复制对象映射器的事实一致。这意味着用于 API 序列化的对象映射器不受相同问题的影响。【参考方案2】:

bootstrap.getObjectMapper() 配置DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES 没有达到预期效果的原因是ConfigurationFactory(稍后用于解析配置的类)在其构造函数中启用了对象映射器的特定功能(请参阅here):

public ConfigurationFactory(Class<T> klass,
                            Validator validator,
                            ObjectMapper objectMapper,
                            String propertyPrefix) 
    ...
    this.mapper = objectMapper.copy();
    mapper.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    ...

无法直接更改ConfigurationFactory 的行为,但Dropwizard 提供了通过Boostrap.setConfigurationFactoryFactory() 覆盖创建它的工厂ConfigurationFactoryFactory 的方法。这允许用不允许覆盖配置并将其传递给ConfigurationFactory的代理替换真正的ObjectMapper

  bootstrap.setConfigurationFactoryFactory(
      (klass, validator, objectMapper, propertyPrefix) -> 
          return new ConfigurationFactory<>(klass, validator,
              new ObjectMapperProxy(objectMapper), propertyPrefix);
      
  );

ObjectMapperProxy 的代码在下面忽略启用FAIL_ON_UNKNOWN_PROPERTIES 的尝试:

private static class ObjectMapperProxy extends ObjectMapper 

    private ObjectMapperProxy(ObjectMapper objectMapper) 
        super(objectMapper);
    

    private ObjectMapperProxy(ObjectMapperProxy proxy) 
        super(proxy);
    

    @Override
    public ObjectMapper enable(DeserializationFeature feature) 
        // do not allow Dropwizard to enable the feature
        if (!feature.equals(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) 
            super.enable(feature);
        
        return this;
    

    @Override
    public ObjectMapper copy() 
        return new ObjectMapperProxy(this);
    


请注意,除了覆盖 enable 以跳过 FAIL_ON_UNKNOWN_PROPERTIES 之外,copy 也被实现(连同额外的构造函数),因为 ConfigurationFactory 需要对象映射器来支持复制。

虽然上述解决方案有效,但它显然是一种解决方法,我建议升级到更新的 Dropwizard 版本。新的 Dropwizard 使 ObjectMapper 配置更易于覆盖(例如,请参阅 Dropwizard 1.1.x 中的 this Dropwizard commit)。

【讨论】:

以上是关于配置 Dropwizard ObjectMapper 以配置忽略未知的主要内容,如果未能解决你的问题,请参考以下文章

配置 Dropwizard ObjectMapper 以配置忽略未知

使用Dropwizard时配置Jackson映射器

dropwizard 应用程序中的配置更改以与 react browserHistory 一起使用

通过命令行将一个空数组传递给 Dropwizard

SOA专题---Dropwizard与Spring Boot比较

在 Dropwizard 中将 http 连接重定向到 https 的首选方式