json string formatting

Keywords: Java JSON

Recently, when docking with a third-party system, we need to save their request parameters, but that long string of json is not easy to read, so we want to format it. There are many tools, but I want to make one for myself.
At the beginning of the implementation, a lot of judgment was used, and the logic was very convoluted. Later, I remembered that I had read the source code of a template engine before, which used the state diagram, so I tried to use it.

public class Main {
    private static String NEW_LINE = "\r\n";

    public static void main(String[] args) {
        String json = "[{\"name\": \"wen\",\"age\": 12,\"flag\": true,\"job\": [{\"name\":\"java\"},{\"name\": \"c++\"}]},{\"name\": \"yun\",\"age\": 13,\"flag\": false}]";

        System.out.println(format(json));
    }

    private static String format(String json) {
        // Remove the original format
        json = json.replace("\n", "").replace("\r", "").replace("\t", "");

        StringBuilder sb = new StringBuilder();
        int prevStatus = 0;// Previous state
        int level = 0;// Indentation level

        for (char c : json.toCharArray()) {
            int oper = getOperation(prevStatus, c);
            switch (oper) {
                case 1:
                    sb.append(NEW_LINE).append(getTab(level));
                    break;
                case 2:
                    level++;
                    sb.append(NEW_LINE).append(getTab(level));
                    break;
                case 3:
                    level--;
                    sb.append(NEW_LINE).append(getTab(level));
                    break;
                case 4:
                    sb.append(' ');
                    break;
            }
            sb.append(c);
            prevStatus = getStatus(c);
        }

        return sb.toString();
    }

    // Return: 0 output directly, 1 line feed, 2 increase indent and line feed, 3 decrease indent and line feed, 4 add space before
    private static int[][] statusArr = new int[][] {
        {0, 0, 0, 0, 0, 3},  // Ordinary character
        {1, 2, 2, 0, 0, 0},  // {[
        {2, 0, 4, 0, 0, 0},  // :
        {3, 1, 4, 0, 0, 0},  // ,
        {4, 0, 0, 0, 0, 3},};// }]

    // Determine operation based on previous status and current character
    private static int getOperation(int status, char c) {
        return statusArr[status][getStatus(c) + 1];
    }

    // Character conversion to corresponding state
    private static int getStatus(char c) {
        int status = 0;
        switch (c) {
            case '{':
            case '[':
                status = 1;
                break;
            case ':':
                status = 2;
                break;
            case ',':
                status = 3;
                break;
            case '}':
            case ']':
                status = 4;
                break;
        }

        return status;
    }

    // indent
    private static String getTab(int level) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < level; i++) {
            sb.append("    ");
        }
        return sb.toString();
    }
}

results of enforcement

[
    {
        "name": "wen",
        "age": 12,
           "flag": true,
        "job": [
            {
                "name":"java"
            }, {
                "name": "c++"
            }
        ]
    }, {
        "name": "yun",
        "age": 13,
        "flag": false
    }
]

Posted by DiceyJono on Sat, 04 Apr 2020 07:00:01 -0700