在 Jackson 中将 JsonNode 序列化为非常特定的 JSON 格式 [英] Serialize JsonNode to a very specific JSON format in Jackson

查看:35
本文介绍了在 Jackson 中将 JsonNode 序列化为非常特定的 JSON 格式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有要打印的 JsonNode 结果.到目前为止,我正在使用:

I have JsonNode result that I want to print out. So far, I am using:

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
File outputFile = new File(
    getCurOutputDir(), String.format("out.json", getClass().getSimpleName())
);
mapper.writeValue(new FileOutputStream(outputFile), resultNode);

输出类似:

{
  "A" : [ {
    "Ai" : {
      "Ai1" : 42,
      "Ai2" : 55
    }
  } ],
    "B" : [ 86 ]
}

但我需要它采用这种特定格式:

but I need it to be in this specific format:

{
  "A" : [ 
    {
      "Ai" : {
        "Ai1" : 42,
        "Ai2" : 55
      }
    } 
  ],
    "B" : [
      86 
    ]
}

对于上下文,我正在从 JSONObject 过渡到 Jackson,因此第二个输出是由 JSONObject.serialize() 输出的输出.

For context, I am transitioning from JSONObject to Jackson, so the second output is the one that is outputted by JSONObject.serialize().

另外,上面显示的每种格式都有名称吗?它似乎遵守不同的标准.

Also, is there a name for each of the format presented above? It seems like it abides by different standards.

推荐答案

您可以自定义 Jackson 将如何缩进输出.根据您使用的 Jackson 版本,有不同的方法可以实现.

You can customize how Jackson will indent the output. There are different ways to achieve it, according to the Jackson version you are using.

执行以下操作:

DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
Indenter indenter = new DefaultIndenter();
printer.indentObjectsWith(indenter); // Indent JSON objects
printer.indentArraysWith(indenter);  // Indent JSON arrays

ObjectMapper mapper = new ObjectMapper();
mapper.writer(printer).writeValue(new FileOutputStream(outputFile), node);

默认情况下,将使用 2 个空格.对于不同数量的空格,请使用 DefaultIndenter 接收字符串以缩进级别和行分隔符的构造函数:

By default, 2 spaces will be used. For a different number of spaces, use the DefaultIndenter constructor that receives a string to indent levels and the line separator:

Indenter indenter = new DefaultIndenter("      ", DefaultIndenter.SYS_LF);

Jackson 2.4 及更早版本

执行以下操作:

DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
Indenter indenter = new Lf2SpacesIndenter();
printer.indentObjectsWith(indenter); // Indent JSON objects
printer.indentArraysWith(indenter);  // Indent JSON arrays

ObjectMapper mapper = new ObjectMapper();
mapper.writer(printer).writeValue(new FileOutputStream(outputFile), node);

Lf2SpacesIndenter 限制为 2 个空格,您无法更改.

The Lf2SpacesIndenter is limited to 2 spaces and you cannot change it.

如果您需要不同数量的空格,则需要编写自定义实现.这是一个使用与 DefaultIndenter 在 Jackson 2.5 中引入:

If you need a different number of spaces, you need to write your custom implementation. Here's one that uses the same code as the DefaultIndenter introduced in Jackson 2.5:

/**
 * Default linefeed-based indenter.
 */
public class CustomSpaceIndenter extends DefaultPrettyPrinter.NopIndenter {

    public final static String SYS_LF;
    static {
        String lf;
        try {
            lf = System.getProperty("line.separator");
        } catch (Throwable t) {
            lf = "
"; // fallback when security manager denies access
        }
        SYS_LF = lf;
    }

    public static final CustomSpaceIndenter SYSTEM_LINEFEED_INSTANCE = 
            new CustomSpaceIndenter("  ", SYS_LF);

    /**
     * We expect to rarely get indentation deeper than this number of levels,
     * and try not to pre-generate more indentations than needed.
     */
    private final static int INDENT_LEVELS = 16;
    private final char[] indents;
    private final int charsPerLevel;
    private final String eol;

    /**
     * Indent with two spaces and the system's default line feed
     */
    public CustomSpaceIndenter() {
        this("  ", SYS_LF);
    }

    /**
     * Create an indenter which uses the <code>indent</code> string to indent one level
     *  and the <code>eol</code> string to separate lines.
     */
    public CustomSpaceIndenter(String indent, String eol)  {
        charsPerLevel = indent.length();
        indents = new char[indent.length() * INDENT_LEVELS];
        int offset = 0;
        for (int i=0; i<INDENT_LEVELS; i++) {
            indent.getChars(0, indent.length(), indents, offset);
            offset += indent.length();
        }
        this.eol = eol;
    }

    public CustomSpaceIndenter withLinefeed(String lf) {
        if (lf.equals(eol)) {
            return this;
        }
        return new CustomSpaceIndenter(getIndent(), lf);
    }

    public CustomSpaceIndenter withIndent(String indent) {
        if (indent.equals(getIndent())) {
            return this;
        }
        return new CustomSpaceIndenter(indent, eol);
    }

    public String getEol() {
        return eol;
    }

    public String getIndent() {
        return new String(indents, 0, charsPerLevel);
    }

    @Override
    public boolean isInline() { 
        return false;
    }

    @Override
    public void writeIndentation(JsonGenerator jg, int level) throws IOException {
        jg.writeRaw(eol);
        if (level > 0) { // should we err on negative values (as there's some flaw?)
            level *= charsPerLevel;
            while (level > indents.length) { // unlike to happen but just in case
                jg.writeRaw(indents, 0, indents.length); 
                level -= indents.length;
            }
            jg.writeRaw(indents, 0, level);
        }
    }
}

可以如下使用:

Indenter indenter = new CustomSpaceIndenter("      ", CustomSpaceIndenter.SYS_LF);

这篇关于在 Jackson 中将 JsonNode 序列化为非常特定的 JSON 格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆