34

I have a valid JSON String that I want to tidy/format such that each property/value pair is on its own line, etc. (it currently is on one line with no spaces/line breaks).

I am using the Apache Sling JSONObject to model my JSON Object and turn it into a String, so if the Sling JSONObject can be set to output a tidy string (which I do not think it can) that would work too.

If I need a 3rd party lib I would prefer one with as few dependencies as possibles (such as Jackson which only requires the std JDK libs).

gawi
  • 2,843
  • 4
  • 29
  • 44
empire29
  • 3,729
  • 6
  • 45
  • 71

9 Answers9

50

With gson you can do:

JsonParser parser = new JsonParser();
Gson gson = new GsonBuilder().setPrettyPrinting().create();

JsonElement el = parser.parse(jsonString);
jsonString = gson.toJson(el); // done
Ali Shakiba
  • 20,549
  • 18
  • 61
  • 88
30

Many JSON libraries have a special .toString(int indentation) method

// if it's not already, convert to a JSON object
JSONObject jsonObject = new JSONObject(jsonString);
// To string method prints it with specified indentation
System.out.println(jsonObject.toString(4));
Oded Breiner
  • 28,523
  • 10
  • 105
  • 71
27

You don't need an outside library.

Use the built in pretty printer in Sling's JSONObject: http://sling.apache.org/apidocs/sling5/org/apache/sling/commons/json/JSONObject.html#toString(int)

public java.lang.String toString(int indentFactor) throws JSONException

Make a prettyprinted JSON text of this JSONObject. Warning: This method assumes that the data structure is acyclical.

Parameters:

indentFactor - The number of spaces to add to each level of indentation.

Returns: a printable, displayable, portable, transmittable representation of the object, beginning with { (left brace) and ending with } (right brace).

Throws: JSONException - If the object contains an invalid number.

Freiheit
  • 8,408
  • 6
  • 59
  • 101
9
public static String formatJSONStr(final String json_str, final int indent_width) {
    final char[] chars = json_str.toCharArray();
    final String newline = System.lineSeparator();

    String ret = "";
    boolean begin_quotes = false;

    for (int i = 0, indent = 0; i < chars.length; i++) {
        char c = chars[i];

        if (c == '\"') {
            ret += c;
            begin_quotes = !begin_quotes;
            continue;
        }

        if (!begin_quotes) {
            switch (c) {
            case '{':
            case '[':
                ret += c + newline + String.format("%" + (indent += indent_width) + "s", "");
                continue;
            case '}':
            case ']':
                ret += newline + ((indent -= indent_width) > 0 ? String.format("%" + indent + "s", "") : "") + c;
                continue;
            case ':':
                ret += c + " ";
                continue;
            case ',':
                ret += c + newline + (indent > 0 ? String.format("%" + indent + "s", "") : "");
                continue;
            default:
                if (Character.isWhitespace(c)) continue;
            }
        }

        ret += c + (c == '\\' ? "" + chars[++i] : "");
    }

    return ret;
}
gawi
  • 2,843
  • 4
  • 29
  • 44
Janardhan
  • 99
  • 1
  • 2
  • 1
    Nice, this worked without any external library. I would make here a few changes however: follow java coding conventions and use StringBuilder instead of String concatenation. – andronix Jan 19 '18 at 19:11
6

+1 for JohnS's gson answer, but here's a way with the "standard" JSONObject library:

public class JsonFormatter{

    public static String format(final JSONObject object) throws JSONException{
        final JsonVisitor visitor = new JsonVisitor(4, ' ');
        visitor.visit(object, 0);
        return visitor.toString();
    }

    private static class JsonVisitor{

        private final StringBuilder builder = new StringBuilder();
        private final int indentationSize;
        private final char indentationChar;

        public JsonVisitor(final int indentationSize, final char indentationChar){
            this.indentationSize = indentationSize;
            this.indentationChar = indentationChar;
        }

        private void visit(final JSONArray array, final int indent) throws JSONException{
            final int length = array.length();
            if(length == 0){
                write("[]", indent);
            } else{
                write("[", indent);
                for(int i = 0; i < length; i++){
                    visit(array.get(i), indent + 1);
                }
                write("]", indent);
            }

        }

        private void visit(final JSONObject obj, final int indent) throws JSONException{
            final int length = obj.length();
            if(length == 0){
                write("{}", indent);
            } else{
                write("{", indent);
                final Iterator<String> keys = obj.keys();
                while(keys.hasNext()){
                    final String key = keys.next();
                    write(key + " :", indent + 1);
                    visit(obj.get(key), indent + 1);
                    if(keys.hasNext()){
                        write(",", indent + 1);
                    }
                }
                write("}", indent);
            }

        }

        private void visit(final Object object, final int indent) throws JSONException{
            if(object instanceof JSONArray){
                visit((JSONArray) object, indent);
            } else if(object instanceof JSONObject){
                visit((JSONObject) object, indent);
            } else{
                if(object instanceof String){
                    write("\"" + (String) object + "\"", indent);
                } else{
                    write(String.valueOf(object), indent);
                }
            }

        }

        private void write(final String data, final int indent){
            for(int i = 0; i < (indent * indentationSize); i++){
                builder.append(indentationChar);
            }
            builder.append(data).append('\n');
        }

        @Override
        public String toString(){
            return builder.toString();
        }

    }

}

Usage:

public static void main(final String[] args) throws JSONException{
    final JSONObject obj =
            new JSONObject("{\"glossary\":{\"title\": \"example glossary\", \"GlossDiv\":{\"title\": \"S\", \"GlossList\":{\"GlossEntry\":{\"ID\": \"SGML\", \"SortAs\": \"SGML\", \"GlossTerm\": \"Standard Generalized Markup Language\", \"Acronym\": \"SGML\", \"Abbrev\": \"ISO 8879:1986\", \"GlossDef\":{\"para\": \"A meta-markup language, used to create markup languages such as DocBook.\", \"GlossSeeAlso\": [\"GML\", \"XML\"]}, \"GlossSee\": \"markup\"}}}}}");
    System.out.println(JsonFormatter.format(obj));
}

Output:

{
    glossary :
    {
        title :
        "example glossary"
        ,
        GlossDiv :
        {
            GlossList :
            {
                GlossEntry :
                {
                    SortAs :
                    "SGML"
                    ,
                    GlossDef :
                    {
                        GlossSeeAlso :
                        [
                            "GML"
                            "XML"
                        ]
                        ,
                        para :
                        "A meta-markup language, used to create markup languages such as DocBook."
                    }
                    ,
                    GlossSee :
                    "markup"
                    ,
                    GlossTerm :
                    "Standard Generalized Markup Language"
                    ,
                    ID :
                    "SGML"
                    ,
                    Acronym :
                    "SGML"
                    ,
                    Abbrev :
                    "ISO 8879:1986"
                }
            }
            ,
            title :
            "S"
        }
    }
}
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
5

The jackson way:

private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
...
OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(node);
1

Underscore-java has statistic method U.formatJson(json). I am the maintainer of the library.

U.formatJson("{\"a\":{\"b\":\"data\"}}");

// {
//    "a": {
//      "b": "data"
//    }
// }
Valentyn Kolesnikov
  • 2,029
  • 1
  • 24
  • 31
1

The JSON string will have a leading "[" and a trailing "]". Remove these and then use the split method from String to separate the items into an array. You can then iterate through your array and place the data into relevant areas.

Travis J
  • 81,153
  • 41
  • 202
  • 273
1

if your using CQ5 or any JCR based CMS as i guess :)

you can use java json parser to do the job. it has a JSONObject class and a toString() method to convert it to String.

for further reference refer

http://json.org/java/

Rajesh Pantula
  • 10,061
  • 9
  • 43
  • 52
  • 1
    Not sure how i overlooked it, but the JSONObject.toString() has an override method .toString(int indent) which when used prettifies up the JSON String representation. Merely calling JSONObject.toString() however, does not. – empire29 Dec 22 '11 at 04:04