YAML对象转字符串:Jackson与SnakeYAML格式匹配问题求助
解决YAML对象转字符串的格式匹配问题
原始目标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":""}'
方案一:使用Jackson Databind 实现匹配格式
针对你遇到的双引号统一、content字段JSON转义换行问题,通过以下配置调整:
完整代码
ObjectMapper mapper = new ObjectMapper(new YAMLFactory() .disable(Feature.WRITE_DOC_START_MARKER) // 禁用字符串自动换行 .disable(Feature.SPLIT_LINES) // 强制字符串带引号 .configure(YAMLGenerator.Feature.MINIMIZE_QUOTES, false)); // 配置蛇形命名策略 mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); // 为特定字段配置差异化引号序列化 SimpleModule module = new SimpleModule(); module.addSerializer(String.class, new JsonSerializer<String>() { @Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { String currentFieldName = gen.getOutputContext().getCurrentName(); // 为error_gen_info下的目标字段使用单引号 if ("content_type".equals(currentFieldName) || "content".equals(currentFieldName)) { ((YAMLGenerator) gen).writeString(value, YAMLGenerator.SingleQuoteStyle.SINGLE_QUOTED); } else { // 其他字符串使用双引号 gen.writeString(value); } } }); mapper.registerModule(module); try { result = mapper.writeValueAsString(yamlObject); } catch (JsonProcessingException e) { log.warn("Error parsing YAML object to string. Message: {}. Cause: {}", e.getMessage(), e.getCause()); }
关键配置说明
- 禁用换行:通过
disable(Feature.SPLIT_LINES)避免content字段的JSON内容被自动拆分换行 - 引号控制:关闭
MINIMIZE_QUOTES强制所有字符串带引号,再通过自定义序列化器为指定字段设置单引号 - 蛇形命名:保持原有配置自动将驼峰字段转为下划线格式
方案二:使用SnakeYAML 实现匹配格式
针对你遇到的类标识残留、键名未转下划线、引号规则不匹配三个问题,调整配置如下:
完整代码
// 自定义Representer处理命名策略、类标识和引号规则 class CustomRepresenter extends Representer { public CustomRepresenter() { super(); // 禁用类类型标识输出 this.getPropertyUtils().setSkipMissingProperties(true); // 配置驼峰转下划线的命名策略 this.getPropertyUtils().setNamingStrategy(new NamingStrategy() { @Override public String translate(String propertyName) { return propertyName.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase(); } }); } // 重写字符串序列化逻辑,按字段层级设置引号 @Override protected Node representData(Object data) { if (data instanceof String) { String value = (String) data; String fieldPath = getCurrentFieldPath(); // trace_info下的字符串用双引号 if (fieldPath.startsWith("trace_info.")) { return representScalar(Tag.STR, value, DumperOptions.ScalarStyle.DOUBLE_QUOTED); } // error_gen_info下的字符串用单引号 else if (fieldPath.startsWith("error_gen_info.")) { return representScalar(Tag.STR, value, DumperOptions.ScalarStyle.SINGLE_QUOTED); } } return super.representData(data); } // 获取当前序列化的字段完整路径 private String getCurrentFieldPath() { StringBuilder path = new StringBuilder(); for (Object context : getRepresenterState().getContext()) { if (context instanceof ScalarNode) { if (path.length() > 0) { path.insert(0, "."); } path.insert(0, ((ScalarNode) context).getValue()); } } return path.toString(); } } // 初始化输出配置 DumperOptions options = new DumperOptions(); options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); // 使用自定义Representer生成YAML Yaml yaml = new Yaml(new CustomRepresenter(), options); result = yaml.dump(yamlObject);
关键配置说明
- 去除类标识:通过
setSkipMissingProperties(true)禁用根节点的类类型标记输出 - 驼峰转下划线:自定义
NamingStrategy实现字段名的自动转换 - 差异化引号:重写
representData方法,根据字段所属层级判断使用单引号或双引号
内容的提问来源于stack exchange,提问作者Juan2
相关产品推荐
相关产品推荐

