英文:
Escape pipe symbol in Spring REST Docs
问题
我需要记录一个接受由以下类表示的JSON的API:
public class Message {
@NotNull(message = "Sender cannot be null")
private String sender;
@Pattern(regexp="HI|HELLO", message = "Message can be only 'HI' or 'HELLO'")
private String content;
// 构造函数,Getter和Setter..
}
Spring Docs自动生成以下片段:
.Request fields:
|===
|Path|Type|Constraints|Description
|sender
|String
|Must not be null
|Sender of the message
|content
|String
|Must match the regular expression `HI|HELLO`
|Content of the message
|===
这被Asciidoctor用于创建PDF中的表格。然而,在PDF中,表格被打断了(因为有管道符号):
我如何在正则表达式中转义管道符号?
我找到了这个问题,但似乎与另一个项目有关。
这是用于生成文档的测试类(JUnit5):
@WebMvcTest(HomeController.class)
@AutoConfigureRestDocs(outputDir = "target/snippets")
public class HomeControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void postMessageTest() throws Exception {
ConstrainedFields constrainedFields = new ConstrainedFields(Message.class);
this.mockMvc
.perform(post("/message").content("{\"sender\":\"Marc\",\"content\":\"HI\"}")
.characterEncoding("utf-8")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print()).andExpect(status().isOk())
.andDo(document("home-message", requestFields(
attributes(key("title").value("Request fields:")),
constrainedFields.withPath("sender").description("Sender of the message"),
constrainedFields.withPath("content").description("Content of the message")
)));
}
private static class ConstrainedFields {
private final ConstraintDescriptions constraintDescriptions;
ConstrainedFields(Class<?> input) {
this.constraintDescriptions = new ConstraintDescriptions(input);
}
private FieldDescriptor withPath(String property) {
return fieldWithPath(property).attributes(key("constraints").value(
// 假设每个属性只有一个约束
constraintDescriptions.descriptionsForProperty(property).get(0)));
}
}
}
复现此问题的完整项目在这里。
英文:
I need to document an API that accepts a JSON represented by this class:
public class Message {
@NotNull(message = "Sender cannot be null")
private String sender;
@Pattern(regexp="HI|HELLO",message = "Message can be only 'HI' or 'HELLO'")
private String content;
// Constructor, Getters and Setters..
}
Spring Docs autogenerates the following snippet:
.Request fields:
|===
|Path|Type|Constraints|Description
|sender
|String
|Must not be null
|Sender of the message
|content
|String
|Must match the regular expression `HI|HELLO`
|Content of the message
|===
Which is used by Asciidoctor to create a table in the pdf. However, in the pdf, the table is broken (because of the pipe):
How can I escape the pipe within the regular expression?
I found this issue, but seems to be related to another project.
This is the test class to generate the documentation (JUnit5):
@WebMvcTest(HomeController.class)
@AutoConfigureRestDocs(outputDir = "target/snippets")
public class HomeControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void postMessageTest() throws Exception {
ConstrainedFields constrainedFields = new ConstrainedFields(Message.class);
this.mockMvc
.perform(post("/message").content("{\"sender\":\"Marc\",\"content\":\"HI\"}")
.characterEncoding("utf-8")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print()).andExpect(status().isOk())
.andDo(document("home-message", requestFields(
attributes(key("title").value("Request fields:")),
constrainedFields.withPath("sender").description("Sender of the message"),
constrainedFields.withPath("content").description("Content of the message")
)));
}
private static class ConstrainedFields {
private final ConstraintDescriptions constraintDescriptions;
ConstrainedFields(Class<?> input) {
this.constraintDescriptions = new ConstraintDescriptions(input);
}
private FieldDescriptor withPath(String property) {
return fieldWithPath(property).attributes(key("constraints").value(
// Let's assume there is only one constraint for each property
constraintDescriptions.descriptionsForProperty(property).get(0)));
}
}
}
The full project to reproduce the issue is here.
答案1
得分: 1
可能不是最好的解决方案,但经过一些研究,我发现一个简单的\
字符足以在asciidoctor
文档中转义管道符号(来源)。因此,我们的目标是在.adoc
片段中获取这一行:
|Must match the regular expression `HI\|HELLO`
这是从您的代码中提取“约束描述”的方法:
private FieldDescriptor withPath(String property) {
return fieldWithPath(property).attributes(key("constraints").value(
// 假设每个属性只有一个约束
constraintDescriptions.descriptionsForProperty(property).get(0)));
}
在这里,我们对将在.adoc
中编写的文本拥有“完全控制权”。例如,我们可以从constraintDescriptions.descriptionsForProperty(property)
中获取约束描述,对其进行转义,然后将转义后的字符串传递给.value()
:
private FieldDescriptor withPath(String property) {
// 假设每个属性只有一个约束
String desc = constraintDescriptions.descriptionsForProperty(property).get(0);
desc = desc.replace("|", "\\|");
return fieldWithPath(property).attributes(key("constraints").value(desc));
}
这将在.adoc
中生成已转义的行,并且在.pdf
中将被正确渲染:
英文:
probably not the best solution, but, after doing little research, I found out that a simple \
character is enough to escape pipe character in asciidoctor
documents (source). our goal then is to get this line in the .adoc
snippet:
|Must match the regular expression `HI\|HELLO`
this is the method that extracts "constraints descriptions" in your code:
private FieldDescriptor withPath(String property) {
return fieldWithPath(property).attributes(key("constraints").value(
// Let's assume there is only one constraint for each property
constraintDescriptions.descriptionsForProperty(property).get(0)));
}
here we have "full control" over the text that will be written in the .adoc
. we could for example take the constraint description from constraintDescriptions.descriptionsForProperty(property)
, apply our escaping and than pass the escaped string to .value()
:
private FieldDescriptor withPath(String property) {
// Let's assume there is only one constraint for each property
String desc = constraintDescriptions.descriptionsForProperty(property).get(0);
desc = desc.replace("|", "\\|");
return fieldWithPath(property).attributes(key("constraints").value(desc));
}
this will produce the escaped line in the .adoc
and will be correctly rendered in the .pdf
:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论