如何为 Spring REST Docs 编写自定义类型验证器?

How to write custom type validator for Spring REST Docs?

在 Spring REST 文档中,我可以记录 JSON 响应的字段。此外,我可以指定可以传递 JsonFieldType 的类型,例如JsonFieldType.STRIGN。这实际上将被验证,这意味着测试将失败,例如而是返回一个数字。

(...)
    .andDo( document( "one-valid-connection",
          pathParameters( parameterWithName( "ip" ).description( "The requested IPv4 address." ) ),
          responseFields( 
                fieldWithPath( "username" ).type( JsonFieldType.STRING ).description( "The name of the user that initiated the connection." ),
                fieldWithPath( "ipAddress" ).type( JsonFieldType.STRING ).description( "The IPv4 address of the user." ),
                fieldWithPath( "startTime" ).type( JsonFieldType.STRING ).description( "The time (ISO 8601 format) when the connection has been initiated." ),
                fieldWithPath( "stopTime" ).type( JsonFieldType.STRING ).description( "The time (ISO 8601 format) when the connection has been terminated or `null` if connection is still active." )
           )
    ) );

我的问题是,是否可以编写自定义类型来支持例如IP 地址、ISO 时间戳、枚举,甚至可能是有效的数字范围 以支持自定义验证(例如正则表达式或更复杂的逻辑)?

作为伪代码,类似于

          responseFields( 
                fieldWithPath( "username" ).type( JsonFieldType.STRING )
                fieldWithPath( "ipAddress" ).type( CustomTypes.IPV4_ADDRESS ),
                fieldWithPath( "startTime" ).type( CustomTypes.ISO8601_TIMESTAMP ),
                fieldWithPath( "stopTime" ).type( CustomTypes.ISO8601_TIMESTAMP ),
                fieldWithPath( "type" ).type( CustomTypes.CONNECTION_ENUM ),
                fieldWithPath( "duration" ).type( CustomTypes.createIntRange(0,999999) )
           )

恕我直言,没有任何理智、直接(即仅利用 Spring 开放扩展的点)解决方案。

Spring Restdocs 的主要目的是文档,而不是验证 API。当我浏览源代码时,有效负载的实际实例仅针对预定义类型进行测试。数值不再进一步分析。尽管您可以将任何 Object 作为字段描述符类型,即您不仅限于 JsonFieldType class 的对象,整个对象基本上只转换为 toString 以写入进入一些 asciidoc 文档,仅此而已。

顺便说一句,我 也有使用 Restdocs 作为结构验证工具的想法。对于我的情况,我最终找到了可接受的解决方案。 Spring Restdocs 源非常封闭,因此根据我探索内部结构的经验,我建议您不要尝试任何 hacky 解决方案,例如覆盖 org.springframework.restdocs.payload.JsonContentHandler#determineFieldTypeorg.springframework.restdocs.payload.JsonFieldTypeResolver#resolveFieldType 方法(这需要通过 class-instrumenting 工具破坏可见性保护)。

另一个想法是使用 bean validation annotations