Java 8下用旧版Jackson将JSONObject转为带|的指定YAML格式
解决Jackson 2.7.6生成带|符号的YAML格式问题
方法一:字符串替换(最简单直接)
生成标准YAML后,通过正则匹配替换目标行,快速实现格式修改:
private static String processFilesForYml(JSONObject a_Obj) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); JsonNode jsonNode = objectMapper.readTree(a_Obj.toString()); String yamlStr = new YAMLMapper().writeValueAsString(jsonNode); // 匹配"examples:"开头的行,替换为带|的格式 return yamlStr.replaceAll("(\\s*)examples:\\n\\s+-", "$1examples: |\\n\\s+-"); }
该方法适合结构固定的场景,仅修改examples字段的输出格式,不改变原数据类型。
方法二:自定义数组序列化器(精准控制)
通过自定义Jackson序列化器,仅对examples字段的数组进行特殊处理,输出带|的块格式:
1. 实现自定义序列化器
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.node.JsonArray; import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; import java.io.IOException; public class ExamplesArraySerializer extends JsonSerializer<JsonArray> { @Override public void serialize(JsonArray value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 仅处理名为"examples"的字段,且是YAML输出场景 if ("examples".equals(gen.getOutputContext().getCurrentName()) && gen instanceof YAMLGenerator) { YAMLGenerator yamlGen = (YAMLGenerator) gen; yamlGen.writeRaw(" |\n"); // 获取当前缩进级别,生成对应空格 int indent = yamlGen.getCurrentIndent(); StringBuilder indentSb = new StringBuilder(); for (int i = 0; i < indent; i++) { indentSb.append(' '); } // 遍历数组生成每行的列表项 for (int i = 0; i < value.size(); i++) { yamlGen.writeRaw(indentSb + "- \"" + value.get(i).asText() + "\"\n"); } } else { // 其他场景按默认方式序列化数组 gen.writeStartArray(); for (int i = 0; i < value.size(); i++) { gen.writeString(value.get(i).asText()); } gen.writeEndArray(); } } }
2. 配置YAMLMapper并使用
private static String processFilesForYml(JSONObject a_Obj) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); JsonNode jsonNode = objectMapper.readTree(a_Obj.toString()); YAMLMapper yamlMapper = new YAMLMapper(); // 注册自定义序列化器 yamlMapper.registerModule(new com.fasterxml.jackson.databind.module.SimpleModule() .addSerializer(JsonArray.class, new ExamplesArraySerializer())); return yamlMapper.writeValueAsString(jsonNode); }
此方法精准控制examples字段的输出格式,保持原数组数据类型,其他数组不受影响。
方法三:转换数组为多行字符串(适合无需反序列化场景)
将原examples数组转换为多行字符串,利用Jackson的特性输出块标格式:
private static String processFilesForYml(JSONObject a_Obj) throws Exception { // 遍历nlu数组,将examples数组转换为多行字符串 JSONArray nluArray = a_Obj.getJSONArray("nlu"); for (int i = 0; i < nluArray.length(); i++) { JSONObject nluItem = nluArray.getJSONObject(i); if (nluItem.has("examples")) { JSONArray examples = nluItem.getJSONArray("examples"); StringBuilder sb = new StringBuilder(); for (int j = 0; j < examples.length(); j++) { sb.append("- \"").append(examples.getString(j)).append("\"\n"); } if (sb.length() > 0) { sb.setLength(sb.length() - 1); // 移除最后一个换行符 } nluItem.put("examples", sb.toString()); } } ObjectMapper objectMapper = new ObjectMapper(); JsonNode jsonNode = objectMapper.readTree(a_Obj.toString()); YAMLMapper yamlMapper = new YAMLMapper(); // 开启多行字符串以块标量输出 yamlMapper.enable(YAMLGenerator.Feature.WRITE_STRINGS_AS_LITERALS); return yamlMapper.writeValueAsString(jsonNode); }
注意:此方法会将examples的数据类型从数组转为字符串,若后续需要反序列化为数组则不适用,仅适合纯输出场景。
内容的提问来源于stack exchange,提问作者Ømi
相关产品推荐
相关产品推荐

