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

查看:134
本文介绍了在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版本,有不同的方法可以实现它。

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及更早版本



以下内容:

Jackson 2.4 and older versions

Do the following:

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

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 = "\n"; // 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天全站免登陆