Created
October 22, 2009 18:44
-
-
Save anonymous/216173 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.github; | |
import java.io.PrintWriter; | |
import java.io.StringWriter; | |
import java.lang.reflect.Type; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.Collections; | |
import java.util.Comparator; | |
import java.util.HashMap; | |
import java.util.LinkedList; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Set; | |
import java.util.SortedSet; | |
import java.util.TreeSet; | |
import java.util.Map.Entry; | |
import com.google.gson.Gson; | |
import com.google.gson.JsonArray; | |
import com.google.gson.JsonElement; | |
import com.google.gson.JsonObject; | |
/** | |
* A decent pretty-printer for Gson. Features include: | |
* | |
* <ul> | |
* <li>Will try to use a single line where possible</li> | |
* <li>Configurable indent string</li> | |
* </ul> | |
* | |
* This file is (c) Copyright 2009 Uprizer Labs LLC It is released to the public under the Lesser GNU Public License | |
* v3.0 See http://www.gnu.org/licenses/lgpl.html for details. | |
* | |
* @author Ian Clarke <ian@uprizer.com>, minor additions by Eric Poggel (NuOrbit Media, nuorbit.com) | |
* @see http://gist.github.com/212791, http://blog.locut.us/main/2009/10/18/a-good-pretty-printer-for-google-gson.html | |
* | |
* @example | |
* new GsonPrettyPrinter(gb.create()).ppJson(some_object); | |
*/ | |
public class GsonPrettyPrinter { | |
private static <V> SortedSet<Entry<String, V>> orderEntrySet(final Set<Entry<String, V>> es) { | |
final TreeSet<Entry<String, V>> ret = new TreeSet<Entry<String, V>>(new Comparator<Entry<String, V>>() { | |
public int compare(final Entry<String, V> o1, final Entry<String, V> o2) { | |
return o1.getKey().compareTo(o2.getKey()); | |
} | |
}); | |
ret.addAll(es); | |
return ret; | |
} | |
private final Gson gson; | |
private static final int MAX_LEN_FOR_ONE_LINE = 150; | |
private final String indent; | |
public GsonPrettyPrinter(final Gson gson) { | |
this(gson, " "); | |
} | |
public GsonPrettyPrinter(final Gson gson, final String indent) { | |
this.gson = gson; | |
this.indent = indent; | |
} | |
public String ppJson(final Object o) { | |
return ppJson(o, null); | |
} | |
public String ppJson(final Object o, Type t) { | |
if (t==null) | |
t = o.getClass(); | |
final StringWriter sw = new StringWriter(); | |
final PrintWriter pw = new PrintWriter(sw); | |
ppJson(o, pw, t); | |
return sw.toString(); | |
} | |
public void ppJson(final Object o, final PrintWriter pw, Type t) { | |
final JsonElement jsonTree = gson.toJsonTree(o, t); | |
final List<String> stringList = toStringList(jsonTree); | |
for (final String s : stringList) { | |
pw.println(s); | |
} | |
} | |
private List<String> arrayToStringList(final JsonArray jsonArray) { | |
final List<List<String>> sll = new LinkedList<List<String>>(); | |
for (final JsonElement arrayElement : jsonArray) { | |
sll.add(toStringList(arrayElement)); | |
} | |
// Can we fit the array on a single line? | |
boolean oneLine = true; | |
int approxLineLength = 0; | |
for (final List<String> sl : sll) { | |
if (sl.size() > 1) { | |
oneLine = false; | |
break; | |
} | |
approxLineLength += sl.get(0).length() + 2; | |
} | |
if (approxLineLength > MAX_LEN_FOR_ONE_LINE) { | |
oneLine = false; | |
} | |
if (oneLine) { | |
final StringBuffer sb = new StringBuffer(approxLineLength * 2 + 10); | |
sb.append("["); | |
boolean first = true; | |
for (final List<String> sl : sll) { | |
if (!first) { | |
sb.append(", "); | |
} | |
first = false; | |
sb.append(sl.get(0)); | |
} | |
sb.append("]"); | |
return Collections.singletonList(sb.toString()); | |
} | |
final LinkedList<String> ret = new LinkedList<String>(); | |
ret.add("["); | |
int oPos = 0; | |
for (final List<String> sl : sll) { | |
oPos++; | |
final int slLen = sl.size(); | |
int pos = 0; | |
for (final String s : sl) { | |
pos++; | |
final boolean needComma = (pos == slLen && oPos < sll.size()); | |
ret.add(indent + s + (needComma ? ", " : "")); | |
} | |
} | |
ret.add("]"); | |
return ret; | |
} | |
private List<String> objectToStringList(final JsonObject jsonObject) { | |
final Map<String, List<String>> slm = new HashMap<String, List<String>>(); | |
for (final Entry<String, JsonElement> e : jsonObject.entrySet()) { | |
slm.put(e.getKey(), toStringList(e.getValue())); | |
} | |
// Can we fit the object on a single line? | |
boolean oneLine = true; | |
int approxLineLength = 0; | |
for (final Entry<String, List<String>> e : slm.entrySet()) { | |
if (e.getValue().size() > 1) { | |
oneLine = false; | |
break; | |
} | |
approxLineLength += e.getKey().length() + e.getValue().get(0).length() + 6; | |
} | |
if (approxLineLength > MAX_LEN_FOR_ONE_LINE) { | |
oneLine = false; | |
} | |
if (oneLine) { | |
final StringBuffer sb = new StringBuffer(approxLineLength * 2 + 10); | |
sb.append("{"); | |
boolean first = true; | |
for (final Entry<String, List<String>> e : orderEntrySet(slm.entrySet())) { | |
if (!first) { | |
sb.append(", "); | |
} | |
first = false; | |
sb.append("\"" + e.getKey() + "\" : " + e.getValue().get(0)); | |
} | |
sb.append("}"); | |
return Collections.singletonList(sb.toString()); | |
} | |
final LinkedList<String> ret = new LinkedList<String>(); | |
ret.add("{"); | |
int oPos = 0; | |
for (final Entry<String, List<String>> e : orderEntrySet(slm.entrySet())) { | |
oPos++; | |
final int slLen = e.getValue().size(); | |
int pos = 0; | |
for (final String s : e.getValue()) { | |
pos++; | |
final boolean needComma = (pos == slLen && oPos < slm.size()); | |
if (pos == 1) { | |
ret.add(indent + "\"" + e.getKey() + "\" : " + s + (needComma ? ", " : "")); | |
} else { | |
ret.add(indent + s + (needComma ? ", " : "")); | |
} | |
} | |
} | |
ret.add("}"); | |
return ret; | |
} | |
private List<String> toStringList(final JsonElement je) { | |
if (je==null || je.isJsonNull()) | |
return new ArrayList<String>(Arrays.asList(new String[]{"null"})); | |
if (je.isJsonPrimitive()) | |
return Collections.singletonList(je.getAsJsonPrimitive().toString()); | |
if (je.isJsonArray()) { | |
final JsonArray jsonArray = je.getAsJsonArray(); | |
return arrayToStringList(jsonArray); | |
} else if (je.isJsonObject()) { | |
final JsonObject jsonObject = je.getAsJsonObject(); | |
return objectToStringList(jsonObject); | |
} | |
throw new RuntimeException("Unsupported Json element: " + je.getClass().getName()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment