我使用JSON -simple,我需要漂亮地打印JSON数据(使其更易于阅读)。

我还没能在那个库中找到这个功能。 这通常是如何实现的?


当前回答

现在这可以通过JSONLib库实现:

http://json-lib.sourceforge.net/apidocs/net/sf/json/JSONObject.html

当(且仅当)你使用重载的toString(int indentationFactor)方法而不是标准的toString()方法。

我已经在以下版本的API上验证了这一点:

<dependency>
  <groupId>org.json</groupId>
  <artifactId>json</artifactId>
  <version>20140107</version>
</dependency>

其他回答

漂亮的打印与GSON一行:

System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(new JsonParser().parse(jsonString)));

除了内联之外,这等价于已接受的答案。

在JSONLib中,你可以这样使用:

String jsonTxt = JSONUtils.valueToString(json, 8, 4);

来自Javadoc:

这招对我很管用,用了杰克逊的话:

mapper.writerWithDefaultPrettyPrinter().writeValueAsString(JSONString)

大多数现有的答案要么依赖于一些外部库,要么需要一个特殊的Java版本。下面是一个简单的代码来漂亮地打印一个JSON字符串,只使用一般的Java api(在Java 7中更高;虽然还没有尝试过旧版本)。

基本思想是基于JSON中的特殊字符来调整格式。例如,如果观察到'{'或'[',代码将创建一个新行并增加缩进级别。

免责声明:我只测试了一些简单的JSON情况(基本的键值对,列表,嵌套JSON),所以它可能需要一些工作更一般的JSON文本,如字符串值内引号,或特殊字符(\n, \t等)。

/**
 * A simple implementation to pretty-print JSON file.
 *
 * @param unformattedJsonString
 * @return
 */
public static String prettyPrintJSON(String unformattedJsonString) {
  StringBuilder prettyJSONBuilder = new StringBuilder();
  int indentLevel = 0;
  boolean inQuote = false;
  for(char charFromUnformattedJson : unformattedJsonString.toCharArray()) {
    switch(charFromUnformattedJson) {
      case '"':
        // switch the quoting status
        inQuote = !inQuote;
        prettyJSONBuilder.append(charFromUnformattedJson);
        break;
      case ' ':
        // For space: ignore the space if it is not being quoted.
        if(inQuote) {
          prettyJSONBuilder.append(charFromUnformattedJson);
        }
        break;
      case '{':
      case '[':
        // Starting a new block: increase the indent level
        prettyJSONBuilder.append(charFromUnformattedJson);
        indentLevel++;
        appendIndentedNewLine(indentLevel, prettyJSONBuilder);
        break;
      case '}':
      case ']':
        // Ending a new block; decrese the indent level
        indentLevel--;
        appendIndentedNewLine(indentLevel, prettyJSONBuilder);
        prettyJSONBuilder.append(charFromUnformattedJson);
        break;
      case ',':
        // Ending a json item; create a new line after
        prettyJSONBuilder.append(charFromUnformattedJson);
        if(!inQuote) {
          appendIndentedNewLine(indentLevel, prettyJSONBuilder);
        }
        break;
      default:
        prettyJSONBuilder.append(charFromUnformattedJson);
    }
  }
  return prettyJSONBuilder.toString();
}

/**
 * Print a new line with indention at the beginning of the new line.
 * @param indentLevel
 * @param stringBuilder
 */
private static void appendIndentedNewLine(int indentLevel, StringBuilder stringBuilder) {
  stringBuilder.append("\n");
  for(int i = 0; i < indentLevel; i++) {
    // Assuming indention using 2 spaces
    stringBuilder.append("  ");
  }
}

所以我也很喜欢json-simple lib,并研究了如何打印它的输出。不幸的是,虽然这是一个悬而未决的问题,但我找不到它的任何代码。所以我想我应该试一试,这是我想出的(使用他们自己的来源)..

public class JsonPrinter {
  
  
  
  public static String toJson(Map<?,?> map) {
    StringBuilder out = new StringBuilder(32);
    new JsonPrinter(out).print(map);
    return out.toString();
  }
  
  
  public static String toJson(List<?> list) {
    StringBuilder out = new StringBuilder(32);
    new JsonPrinter(out).print(list);
    return out.toString();
  }
  
  
  
  
  
  
  
  private final Appendable out;
  private final String indentUnit;
  private final String newLine;
  
  
  private int indents;
  
  public JsonPrinter(Appendable out) {
    this(out, "  ", System.lineSeparator());
  }

  /**
   * 
   */
  public JsonPrinter(Appendable out, String indentUnit, String newLine) {
    this.out = Objects.requireNonNull(out, "null out");
    this.indentUnit = Objects.requireNonNull(indentUnit, "null indentUnit");
    this.newLine = Objects.requireNonNull(newLine, "null newLine");
    
    if (!indentUnit.isBlank())
      throw new IllegalArgumentException(
          "indentUnit must be a blank sequence (quoted): '" + indentUnit + "'");
    if (!"\r\n".equals(newLine) && ! "\n".equals(newLine))
      throw new IllegalArgumentException(
          "unrecognized newLine (quoted): '" + newLine + "'");
  }
  
  
  public void print(List<?> list) throws UncheckedIOException {
    try {
      assert indents == 0;
      printImpl(list);
      assert indents == 0;
    } catch (IOException iox) {
      throw new UncheckedIOException("on print(List): " + list, iox);
    }
  }
  
  
  public void print(Map<?,?> map) throws UncheckedIOException {
    try {
      assert indents == 0;
      printImpl(map);
      assert indents == 0;
    } catch (IOException iox) {
      throw new UncheckedIOException("on print(Map): " + map, iox);
    }
  }
  
  
  protected void printImpl(List<?> list) throws IOException {
    if (list == null) {
      out.append("null");
      return;
    }
    
    
    boolean first = true;
    var iter = list.iterator();
    
    open('[');
    while (iter.hasNext()) {
      if (first)
        first = false;
      else
        out.append(',');
      
      out.append(newLine);
      appendIndents();
      
      appendValue(iter.next());
    }
    close(']');
  }
  
  
  protected void printImpl(Map<?, ?> map) throws IOException {
    if (map == null) {
      out.append("null");
      return;
    }
    
    
    boolean first = true;
    var iter = map.entrySet().iterator();
    
    open('{');
    while (iter.hasNext()) {
      if (first)
        first = false;
      else
        out.append(',');
      
      out.append(newLine);
      appendIndents();
      
      var entry = iter.next();
      print(entry.getKey().toString(), entry.getValue());
    }
    close('}');
  }
  
  
  private void open(char c) throws IOException {
    out.append(c);
    ++indents;
  }
  
  private void close(char c) throws IOException {
    --indents;
    out.append(newLine);
    appendIndents();
    out.append(c);
  }
  
  private void appendIndents() throws IOException {
    for (int count = indents; count-- > 0; )
      out.append(indentUnit);
  }
  
  
  
  private void print(String key, Object value) throws IOException {
    out.append('"');
    appendString(key);
    out.append('"').append(':').append(' ');
    appendValue(value);
  }
  
  
  
  private void appendString(String s) throws IOException {
    for (int i = 0; i < s.length(); i++) {
      char ch = s.charAt(i);
      switch(ch){
      case '"':
        out.append("\\\"");
        break;
      case '\\':
        out.append("\\\\");
        break;
      case '\b':
        out.append("\\b");
        break;
      case '\f':
        out.append("\\f");
        break;
      case '\n':
        out.append("\\n");
        break;
      case '\r':
        out.append("\\r");
        break;
      case '\t':
        out.append("\\t");
        break;
      case '/':
        out.append("\\/");
        break;
      default:
                //Reference: http://www.unicode.org/versions/Unicode5.1.0/
        if ((ch>='\u0000' && ch<='\u001F') || (ch>='\u007F' && ch<='\u009F') || (ch>='\u2000' && ch<='\u20FF')) {
          String ss = Integer.toHexString(ch);
          out.append("\\u");
          for (int k=0; k < 4-ss.length(); k++) {
            out.append('0');
          }
          out.append(ss.toUpperCase());
        }
        else{
          out.append(ch);
        }
      }
    }//for
  }
  
  
  private void appendValue(Object value) throws IOException {
    if (value == null) {
      out.append("null");
      
    } else if (value instanceof String) {
      out.append('"');
      appendString(value.toString());
      out.append('"');
      
    } else if (value instanceof Double) {
      var num = (Double) value;
      if (num.isInfinite() || num.isNaN())
        out.append("null");
      else
        out.append(value.toString());
      
    } else if (value instanceof Float) {
      var num = (Float) value;
      if (num.isInfinite() || num.isNaN())
        out.append("null");
      else
        out.append(value.toString());
      
    } else if (value instanceof Map) {
      printImpl((Map<?,?>) value);
      
    } else if (value instanceof List) {
      printImpl((List<?>) value);
      
//    } else if (value instanceof Number || value instanceof Boolean) {
//      out.append(value.toString());
      
    } else {
      out.append(value.toString());
      
    }
  }

}

它适用于JSONObject和JSONArray,即使它没有依赖于他们..因为这些是常规的Map和List对象。(事实代码是从同一个库中提取的)。

https://github.com/crums-io/io-util/blob/master/src/main/java/io/crums/util/json/JsonPrinter.java