[spring-projects/spring-boot]允许配置 Jackson StreamReadConstraints

2024-05-08 378 views

回答

4

感谢您提出这个问题,@pjfanning。

ObjectMapperSpring Boot 运行的层面上,我不太明白如何配置约束。据我所知,它们必须配置在JsonFactoryBuilder用于创建 的 上,而JsonFactory该 又用于创建ObjectMapper.理想情况下,这JsonFactory应该是一个由.我不知道如何创建一个具有本身已使用相同创建的自定义。MappingJsonFactoryObjectMapperObjectMapperJsonFactoryObjectMapper

@cowtowncoder 如果您有时间的话,能否请您为我们指出正确的方向?

0

MappingJsonFactory从现有的构造一个ObjectMapper,然后尝试覆盖StreamReadConstraints-MappingJsonFactory目前不允许。

我不确定这是否是 jackson-databind 应该有的东西,但 @cowtowncoder 可能会有不同的看法。

如果您无法重构代码,您可以子类化 jackson-databindMappingJsonFactory并添加一个方法来覆盖StreamReadConstraints.

9

@wilkinsona 你能强调一些你担心的代码吗?我查看了 spring-boot,我所能找到的只是大量使用new ObjectMapper().

相反new ObjectMapper(),您可能会发现拥有一个通用的好主意ObjectMapperFactory,这样可以更轻松地new ObjectMapper()用类似的东西替换所有调用ObjectMapperFactory.createObjectMapper()

private static JsonFactory JSON_FACTORY;

// add some code to create JSON_FACTORY with your preferred StreamReadConstraints settings

public static createObjectMapper() {
   return JsonMapper.builder(JSON_FACTORY).build();
}
5

我的担忧是一般性的,并没有真正关注 Spring Boot 代码的任何特定区域。如果 Jackson 中有一种用于配置约束的机制,那么根据我们过去配置 Jackson 的经验,我希望我们能够毫无困难地使用它。这是一种配置机制,与 Jackson 在我正在寻找的其他各个领域提供的配置机制类似。

如果说有一个区域可能值得特别关注,那就是 及其周边地区org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration。此自动配置应用用户的spring.jackson.*应用程序属性并广泛使用 Spring 框架Jackson2ObjectMapperBuilder来实现此目的。如果约束需要可配置,那么一些新spring.jackson.*属性将是用户这样做的明显方法。我还不知道如何将这些属性应用到新ObjectMapper实例或现有实例。

3

Jackson 正在努力使对象映射器变得不可变。您可能需要重新考虑在该级别重新配置的想法。工厂和建筑商是 Jackson 配置发生的地方,或者是事情发生的地方。

6

好的,虽然 @pjfanning 是正确的,因为我们正在转向基于构建器的配置,但出于兼容性原因,确实需要对旧式直接配置提供一些支持。对于新功能,这可能不需要,但StreamReadConstraints我认为我们确实需要一些东西。 Jackson 3.x(仅)将提供/要求完全不变性;在此之前,只能使用具有部分优势的构建器。

我将提出一个jackson-core问题,以确保实际上有一种方法可以通过直接设置配置JsonFactory——我确实相信期望框架切换到构建器风格的构造(更重要的是,将其暴露给用户)是不切实际的杰克逊2.x

编辑:创建https://github.com/FasterXML/jackson-core/issues/962

感谢 @pjfanning 的尽职尽责:我认为这是 2.15.0 Final 必须解决的问题,并且现在是一个很好的解决方案(而不是发布后)。

0

@wilkinsona 我确实添加了明显的 2.x 非构建器机制(请参阅https://github.com/FasterXML/jackson-core/issues/962),即JsonFactory.setStreamReadConstraints().它将在 2.15.0-rc2 中。感谢您概述了这个明显的差距(事后看来,尽管我真的应该提前看到它)。

与往常一样,我们非常感谢 Spring Boot 团队的帮助:尽管我希望 2.15.0 尽快完成,但我也希望避免匆忙和破坏有价值的用户社区的现有使用情况。

3

非常感谢,@cowtowncoder。

5

使用新的 setter,人们可以在 Spring Boot 应用程序中配置约束,而无需在 Boot 中进行任何更改:

@Bean
Jackson2ObjectMapperBuilderCustomizer customStreamReadConstraints() {
    return (builder) -> builder.postConfigurer((objectMapper) -> objectMapper.getFactory()
        .setStreamReadConstraints(StreamReadConstraints.builder().maxNestingDepth(2000).build()));
}

这将确保ObjectMapper通过自动配置创建的任何Jackson2ObjectMapperBuilder内容的最大嵌套深度为 2000。如果调整它们是常见要求,我们仍然可以考虑为这三个约束添加一些配置属性。

5

正确的@wilkinsona,这就是想法。

3

我们添加了一个Jackson2ObjectMapperBuilderCustomizer来修改最大字符串长度,就像 @wilkinsona提到的那样,但我们在使用注入的 ObjectMapper 的测试中没有看到这一点。我们还尝试过StreamReadConstraints.overrideDefaultStreamReadConstraints在应用程序启动时强制覆盖,但同样没有成功。仍触及 20,000,000 的上限。

@Configuration
public class JacksonConfig {
    @Bean
    Jackson2ObjectMapperBuilderCustomizer customStreamReadConstraints() {
        return (builder) -> builder.postConfigurer((objectMapper) -> objectMapper.getFactory()
            .setStreamReadConstraints(StreamReadConstraints.builder().maxStringLength(100000000).build()));
    }
}
public static void main(String[] args) {
    StreamReadConstraints.overrideDefaultStreamReadConstraints(
        StreamReadConstraints.builder().maxStringLength(100000000).build()
    );
    SpringApplication.run(ApiApplication.class, args);
}
8

我可以让它工作的唯一方法是覆盖静态上下文中的默认值,例如


@Configuration
public class JacksonConfig {
    static {
        StreamReadConstraints.overrideDefaultStreamReadConstraints(
            StreamReadConstraints.builder().maxStringLength(100000000).build()
        );
    }
}
2

@jamesdh 我无法重现您在这两种情况下描述的行为。如果overrideDefaultStreamReadConstraints不起作用,听起来好像有其他东西正在配置约束并阻止覆盖的默认值生效。请跟进 Stack Overflow 上的问题,其中包括重现该问题的最小示例。

9

@wilkinsona我开始overrideDefaultStreamReadConstraints工作,但必须从静态上下文中调用它。我猜这意味着第 3 方依赖项中的其他一些 bean/config 可能是原因?我们的代码中没有任何其他内容涉及 ObjectMapper 配置。

6

这确实是杰克逊的问题,但据我所知,对默认值的更改应该会影响com.fasterxml.jackson.core.JsonFactory此后创建的所有内容。正如我上面所说,请关注 Stack Overflow,因为这个问题不适合这个问题。

9

我认为这个问题应该在最初的更改完成后关闭。

如果有后续问题,请将问题提交到适当的位置。

4

我想保持这个问题的开放,看看是否有足够的兴趣来spring.jackson.*配置约束的某些配置属性。与此同时,使用定制器或提前调用StreamReadConstraints.overrideDefaultStreamReadConstraints仍然是推荐的方法。

1

我们刚刚遇到了这种情况。收到已达到的约束限制。能够通过属性来设置它会很好,因为我们所做的大多数配置都是通过这些属性进行的。

8

根据设计,Jackson 并没有提供太多全局配置——它通常作为组件嵌入,因此全局配置往往会破坏非预期位置的使用。

因此 Jackson 端不会添加对属性配置的支持。

编辑:请忽略,根据 @wilkinsona 评论,我对问题感到困惑;与杰克逊一方无关。 Spring 确实有很多相关的可配置性。

3

@wilkinsona 感谢您指出这一点 - 是的,我应该注意问题存在的地方,而不仅仅是查看标题和更新:)

5

@cowtowncoder,我假设 @jjstreet 指的是 Spring Boot 属性。我们已经提供了几个用于配置ObjectMapper实例的方法,并且可以添加它们以为其流读取约束提供基于属性的配置。

这将是非常有用的。我时不时地会达到某些极限。将相同的配置类复制到每个微服务并不是最理想的。发布一个能够通过属性启用配置的 jar 并将其作为依赖项包含在每个应用程序中的问题甚至更大。

6

我想说的是,我们能够通过使用建议的定制器类来绕过流限制约束。

这样的财产会存在于哪里?spring.jackson.deserialization.*

6

我不确定,但它不可能是spring.jackson.deserialization财产,因为它们是Map<DeserializationFeature, Boolean>.我们得考虑一下。