我正在尝试将 YAML 对象转储到 String,但遇到了一些问题。这是原始的 YAML 信息:
trace_enabled: false
error_gen_enabled: false
trace_info:
filter: "filter-12345"
status: 200
method: "PUT"
error_gen_info:
code: 500
rate: 0.35
content_type: 'application/problem+json'
content: '{"status":503,"title":"Internal Server Error","detail":"Too busy","cause":""}'
如果我尝试使用 fastxml.jackson 进行转储,我会尝试以下操作:
ObjectMapper mapper = new ObjectMapper(new YAMLFactory().disable(Feature.WRITE_DOC_START_MARKER));
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
try {
result = mapper.writeValueAsString(yamlObject);
} catch (JsonProcessingException e) {
log.warn("Error parsing YAML object to string. Message: {}. Cause: {}", e.getMessage(), e.getCause());
}
结果:
trace_enabled: false
error_gen_enabled: false
trace_info:
filter: "filter-12345"
status: 200
method: "PUT"
error_gen_info:
code: 500
rate: 0.35
content_type: "application/problem+json"
content: "{\"status\":503,\"title\":\"Internal Server Error\",\"detail\":\"Too busy\"\
,\"cause\":\"\"}"
所以在原文中可以看出,“trace_info”字符串值是双引号的,“error_gen_info”是单引号的。我希望“content_type”和“content”用单引号引起来,因为现在是双引号,并且值 json 看起来很糟糕。
现在如果我尝试使用snakeyaml,我会:
Representer representer = new Representer();
representer.addClassTag(ErrorGenInfo.class, Tag.OMAP);
representer.setDefaultFlowStyle(FlowStyle.BLOCK);
TypeDescription errorGenInfoDesc = new TypeDescription(ErrorGenInfo.class);
errorGenInfoDesc.substituteProperty("content_type", String.class, "getContentType", "setContentType");
representer.addTypeDescription(errorGenInfoDesc);
errorGenInfoDesc.setExcludes("contentType");
Yaml yaml = new Yaml(representer);
result = yaml.dump(yamlObject);
我得到:
!!com.test.BasicTest$Config
errorGenEnabled: false
errorGenInfo:
code: 500
content: '{"status":503,"title":"Internal Server Error","detail":"Too busy","cause":""}'
contentType: application/problem+json
rate: 0.35
traceEnabled: false
traceInfo:
filter: filter-12345
method: PUT
status: 200
这里我得到了不同的结果:
完成此操作后,如何使用这两种处理 YAML 的方法在输出中获得相同的格式? 预先感谢。
从 Jackson 的
YAMLGenerator
的源代码来看,看起来根本不可能使用单引号字符串。我能得到的最接近您预期的输出是直接使用 SnakeYAML
。除了按预期单引号引用的 content_type
字段之外,没有引用任何字符串值。并且 POJO 的字段顺序没有得到维护。我确实设法删除了带有类名的标签,并将字段名称重命名为蛇形大小写。
代码:
import io.github.devatherock.domain.ErrorGenInfo;
import io.github.devatherock.domain.ResponseBody;
import io.github.devatherock.domain.TraceInfo;
import lombok.extern.slf4j.Slf4j;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@Slf4j
public class TestUtil {
public static String toYaml(ResponseBody yamlObject) {
DumperOptions dumperOptions = new DumperOptions();
dumperOptions.setDefaultFlowStyle(FlowStyle.BLOCK);
dumperOptions.setSplitLines(false);
Representer representer = new Representer(dumperOptions);
// To rename fields
addTypeDescription(
Collections.singletonList("content_type"), Collections.singletonList("getContentType"),
Collections.singletonList("setContentType"), new String[]{"contentType"},
Collections.singletonList(String.class), ErrorGenInfo.class, representer
);
addTypeDescription(
Arrays.asList("trace_enabled", "error_gen_enabled", "trace_info", "error_gen_info"),
Arrays.asList("isTraceEnabled", "isErrorGenEnabled", "getTraceInfo", "getErrorGenInfo"),
Arrays.asList("setTraceEnabled", "setErrorGenEnabled", "setTraceInfo", "setErrorGenInfo"),
new String[]{"traceEnabled", "errorGenEnabled", "traceInfo", "errorGenInfo"},
Arrays.asList(Boolean.class, Boolean.class, TraceInfo.class, ErrorGenInfo.class),
ResponseBody.class, representer
);
// To disable the tags with class name
representer.addClassTag(ResponseBody.class, Tag.MAP);
representer.addClassTag(ErrorGenInfo.class, Tag.MAP);
Yaml yaml = new Yaml(representer);
String result = yaml.dump(yamlObject);
LOGGER.info("Result: \n{}", result);
return result;
}
public static void addTypeDescription(
List<String> propertyNames, List<String> getterNames, List<String> setterNames,
String[] propertiesToExclude, List<Class<?>> propertyClasses,
Class<?> beanClass, Representer representer
) {
TypeDescription typeDescription = new TypeDescription(beanClass);
for (int index = 0; index < propertyNames.size(); index++) {
typeDescription.substituteProperty(
propertyNames.get(index), propertyClasses.get(index), getterNames.get(index), setterNames.get(index)
);
}
typeDescription.setExcludes(propertiesToExclude);
representer.addTypeDescription(typeDescription);
}
}
输出YAML:
trace_enabled: false
error_gen_enabled: false
trace_info:
filter: filter-12345
method: PUT
status: 200
error_gen_info:
content_type: application/problem+json
code: 500
content: '{"status":503,"title":"Internal Server Error","detail":"Too busy","cause":""}'
rate: 0.35