简体   繁体   English

在Jackson中将JsonNode序列化为非常特定的JSON格式

[英]Serialize JsonNode to a very specific JSON format in Jackson

I have JsonNode result that I want to print out. 我有要打印的JsonNode结果。 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);

which outputs something like: 输出类似:

{
  "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 
    ]
}

For context, I am transitioning from JSONObject to Jackson, so the second output is the one that is outputted by JSONObject.serialize() . 对于上下文,我正在从JSONObject过渡到Jackson,因此第二个输出是JSONObject.serialize()输出的输出。

Also, is there a name for each of the format presented above? 另外,上面列出的每种格式都有名称吗? It seems like it abides by different standards. 似乎它遵循不同的标准。

You can customize how Jackson will indent the output. 您可以自定义Jackson如何缩进输出。 There are different ways to achieve it, according to the Jackson version you are using. 根据您使用的Jackson版本,有不同的实现方法。

Jackson 2.5 and newer versions 杰克逊2.5及更高版本

Do the following: 请执行下列操作:

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);

By default, 2 spaces will be used. 默认情况下,将使用2个空格。 For a different number of spaces, use the DefaultIndenter constructor that receives a string to indent levels and the line separator: 对于不同数量的空格,请使用DefaultIndenter构造函数,该构造函数接收字符串来缩进级别和行分隔符:

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

Jackson 2.4 and older versions 杰克逊2.4及更低版本

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);

The Lf2SpacesIndenter is limited to 2 spaces and you cannot change it. Lf2SpacesIndenter限制为2个空格,您不能更改它。

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: 这是使用与Jackson 2.5中引入的DefaultIndenter相同的代码的代码:

/**
 * 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);
        }
    }
}

It can be used as following: 可以如下使用:

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

You can setup a custom DefaultPrettyPrinter using this: 您可以使用以下方法设置自定义DefaultPrettyPrinter

DefaultPrettyPrinter pp = new DefaultPrettyPrinter();
pp.indentObjectsWith(new Lf2SpacesIndenter());
pp.indentArraysWith(new Lf2SpacesIndenter("\r\n"));
mapper.writer(pp).writeValue(new FileOutputStream(outputFile), resultNode);

Take a look at the method provided by DefaultPrettyPrinter HERE 看一下DefaultPrettyPrinter 这里提供的方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM