我使用JSON -simple,我需要漂亮地打印JSON数据(使其更易于阅读)。
我还没能在那个库中找到这个功能。 这通常是如何实现的?
我使用JSON -simple,我需要漂亮地打印JSON数据(使其更易于阅读)。
我还没能在那个库中找到这个功能。 这通常是如何实现的?
当前回答
所以我也很喜欢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
其他回答
我的情况是我的项目使用了不支持漂亮打印的遗留(非jsr) JSON解析器。然而,我需要生成漂亮的JSON样本;这是可能的,而不需要添加任何额外的库,只要你使用Java 7及以上:
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine scriptEngine = manager.getEngineByName("JavaScript");
scriptEngine.put("jsonString", jsonStringNoWhitespace);
scriptEngine.eval("result = JSON.stringify(JSON.parse(jsonString), null, 2)");
String prettyPrintedJson = (String) scriptEngine.get("result");
谷歌的GSON可以很好地做到这一点:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonParser jp = new JsonParser();
JsonElement je = jp.parse(uglyJsonString);
String prettyJsonString = gson.toJson(je);
或者因为现在推荐使用来自JsonParser的静态解析方法,你也可以使用这个代替:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonElement je = JsonParser.parseString(uglyJsonString);
String prettyJsonString = gson.toJson(je);
下面是导入语句:
import com.google.gson.*;
这是Gradle的依赖项:
implementation 'com.google.code.gson:gson:2.8.7'
遵循JSON-P 1.0规范(JSR-353),对于给定的JsonStructure (JsonObject或JsonArray),一个更当前的解决方案可能是这样的:
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import javax.json.Json;
import javax.json.JsonStructure;
import javax.json.JsonWriter;
import javax.json.JsonWriterFactory;
import javax.json.stream.JsonGenerator;
public class PrettyJson {
private static JsonWriterFactory FACTORY_INSTANCE;
public static String toString(final JsonStructure status) {
final StringWriter stringWriter = new StringWriter();
final JsonWriter jsonWriter = getPrettyJsonWriterFactory()
.createWriter(stringWriter);
jsonWriter.write(status);
jsonWriter.close();
return stringWriter.toString();
}
private static JsonWriterFactory getPrettyJsonWriterFactory() {
if (null == FACTORY_INSTANCE) {
final Map<String, Object> properties = new HashMap<>(1);
properties.put(JsonGenerator.PRETTY_PRINTING, true);
FACTORY_INSTANCE = Json.createWriterFactory(properties);
}
return FACTORY_INSTANCE;
}
}
漂亮的打印与GSON一行:
System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(new JsonParser().parse(jsonString)));
除了内联之外,这等价于已接受的答案。
所以我也很喜欢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