ai.susi.json.JsonMinifier.java Source code

Java tutorial

Introduction

Here is the source code for ai.susi.json.JsonMinifier.java

Source

/**
 *  JsonMinifier
 *  Copyright 30.07.2015 by Michael Peter Christen, @0rb1t3r
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *  
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *  
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program in the file lgpl21.txt
 *  If not, see <http://www.gnu.org/licenses/>.
 */

package ai.susi.json;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.Deflater;
import java.util.zip.GZIPOutputStream;

import org.json.JSONObject;

import ai.susi.DAO;
import ai.susi.tools.Compression;
import ai.susi.tools.UTF8;

public class JsonMinifier {

    private final ConcurrentHashMap<String, String> key2short, short2key;

    public JsonMinifier() {
        this.key2short = new ConcurrentHashMap<>();
        this.short2key = new ConcurrentHashMap<>();
    }

    public JsonCapsuleFactory minify(JSONObject json) {
        if (json == null)
            return null;
        JSONObject minified = new JSONObject(true);
        for (String key : json.keySet()) {
            String s = this.key2short.get(key);
            if (s == null)
                synchronized (this.key2short) {
                    s = this.key2short.get(key);
                    if (s == null) {
                        s = Integer.toHexString(this.key2short.size());
                        this.key2short.put(key, s);
                        this.short2key.put(s, key);
                    }
                }
            minified.put(s, json.get(key));
        }
        return new JsonCapsuleFactory(minified);
    }

    public class JsonCapsuleFactory implements JsonFactory {

        byte[] capsule; // byte 0 is a flag: 0 = raw json, 1 = compressed json

        private JsonCapsuleFactory(JSONObject jo) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
            GZIPOutputStream out = null;
            try {
                out = new GZIPOutputStream(baos, 1024) {
                    {
                        def.setLevel(Deflater.BEST_COMPRESSION);
                    }
                };
            } catch (IOException e) {
            }
            OutputStreamWriter osw = new OutputStreamWriter(out);
            jo.write(osw);
            try {
                osw.close();
            } catch (IOException e) {
            }
            //byte[] b = new ObjectMapper().writer().writeValueAsBytes(json);
            //byte[] c = Compression.gzip(b);
            byte[] c = baos.toByteArray();
            //if (b.length <= c.length) {
            //    this.capsule = new byte[b.length + 1];
            //    this.capsule[0] = 0;
            //    System.arraycopy(b, 0, this.capsule, 1, b.length);
            //} else {
            this.capsule = new byte[c.length + 1];
            this.capsule[0] = 1;
            System.arraycopy(c, 0, this.capsule, 1, c.length);
            //}
            //System.out.print("DEBUG " + this.getRawJson());
        }

        public JSONObject getJSON() {
            JSONObject minified = getRawJSON();
            JSONObject original = new JSONObject(true);
            for (String key : minified.keySet()) {
                String s = JsonMinifier.this.short2key.get(key);
                assert s != null;
                if (s != null)
                    original.put(s, minified.get(key));
            }
            return original;
        }

        private JSONObject getRawJSON() {
            byte[] x = new byte[this.capsule.length - 1];
            System.arraycopy(this.capsule, 1, x, 0, this.capsule.length - 1);
            if (this.capsule[0] == 1) {
                x = Compression.gunzip(x);
            }
            try {
                JSONObject json = new JSONObject(UTF8.String(x));
                return json;
            } catch (Throwable e) {
                DAO.log("cannot parse capsule \"" + UTF8.String(this.capsule) + "\"");
            }
            return null;
        }

    }

}