eu.jtzipi.project0.common.json.impl.GsonReadWrite.java Source code

Java tutorial

Introduction

Here is the source code for eu.jtzipi.project0.common.json.impl.GsonReadWrite.java

Source

/*
 * Copyright 2016 Langhammer, Tim | Earth | Europe | Potsdam | MBJS | Ref16 <a href="mailto:tim.langhammer@mbjs.brandenburg.de" alt="Kontakt per mail" >Kontakt</a>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package eu.jtzipi.project0.common.json.impl;

import com.google.gson.Gson;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import javafx.util.Builder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.google.gson.stream.JsonToken.BEGIN_ARRAY;
import static com.google.gson.stream.JsonToken.BEGIN_OBJECT;

/**
 * 
 * A wrapper for the <a href="https://github.com/google/gson">gson</a> json read/write API
 * 
 */
public class GsonReadWrite implements IJsonReadWrite {

    private static final Logger gsonLog = LoggerFactory.getLogger(GsonReadWrite.class);

    private GsonReadWrite() {
    }

    public static GsonReadWrite instanceOf() {
        return new GsonReadWrite();
    }

    /**
     * Serialize the object via the <a href="">Gson</a> API to JSON.
     *
     * @param obj The object to serialize
     *
     * @return The JSON
     */
    @Override
    public final String toJson(final Object obj) {
        if (null == obj) {
            return null;
        }

        Gson gson = new Gson();

        gsonLog.info("JSON : " + gson.toJson(obj));

        return gson.toJson(obj);
    }

    /**
     * Parse the JSON to the Java pendants of the contained.
     *
     * @param jsonStr
     *
     * @return
     * @throws IOException
     */
    @Override
    public Map<String, ? extends Object> toObject(final String jsonStr) throws IOException {
        if (null == jsonStr || jsonStr.isEmpty()) {
            return null;
        }

        return new JsonToObject(jsonStr).toObject();
    }

    public static JsonBuilder newSerializer(final boolean htmlSafe, final boolean leniant) {

        return new JsonBuilder(htmlSafe, leniant);

    }

    /**
     * Wrapper for JSON API's, this case it's googles gson API.
     * TODO: nur sinnvolle Ablufe
     * TODO: flexible API
     * TODO: flexibler Writer
     */
    public static final class JsonBuilder implements Builder<String> {

        JsonWriter jsonW;
        StringWriter sw;
        boolean htmlSafe;
        boolean leniant;

        private JsonBuilder(final boolean htmlSafe, final boolean leniant) {
            sw = new StringWriter();
            jsonW = new JsonWriter(sw);
            jsonW.setHtmlSafe(htmlSafe);
            jsonW.setLenient(leniant);
        }

        public JsonBuilder begin() throws IOException {
            jsonW.beginObject();
            return this;
        }

        public JsonBuilder mapEntry(String key, String val) throws IOException {
            Objects.requireNonNull(key, "The key is null");

            jsonW.name(key);
            if (null == val) {
                jsonW.nullValue();
            } else {
                jsonW.value(val);
            }
            return this;
        }

        public JsonBuilder arrayEntries(final String... entries) throws IOException {
            if (null == entries) {
                return this;
            }

            for (String entry : entries) {
                jsonW.value(entry);
            }
            return this;
        }

        public JsonBuilder beginArray(final String name) throws IOException {
            Objects.requireNonNull(name, "The array name is null");

            jsonW.name(name);
            jsonW.beginArray();

            return this;
        }

        public JsonBuilder beginMap(final String name) throws IOException {
            Objects.requireNonNull(name, "The map name is null");

            jsonW.name(name);
            jsonW.beginObject();

            return this;
        }

        public JsonBuilder mapEntries(final Map<String, String> map) throws IOException {
            Objects.requireNonNull(map, "the map is null");

            for (final Map.Entry<String, String> mapEntry : map.entrySet()) {
                mapEntry(mapEntry.getKey(), mapEntry.getValue());
            }

            return this;
        }

        public JsonBuilder endMap() throws IOException {

            jsonW.endObject();

            return this;
        }

        public JsonBuilder endArray() throws IOException {
            jsonW.endArray();
            return this;
        }

        public JsonBuilder close() throws IOException {
            jsonW.endObject();

            return this;
        }

        @Override
        public String build() {
            final String jsonStr = sw.toString();
            try {
                sw.close();
                jsonW.close();
            } catch (IOException ioE) {

                gsonLog.error("[#build] Fehler bei close : " + ioE);

            }
            return jsonStr;
        }

    }

    private static final class JsonToObject {

        private final String json;

        private JsonToObject(final String jsonStr) {
            this.json = jsonStr;
        }

        public Map<String, Object> toObject() throws IOException {
            Map<String, Object> map = null;
            // try/catch for the reader
            try (final JsonReader jr = new JsonReader(new StringReader(json))) {

                map = deserialize(jr);

            } catch (IOException ioE) {

                gsonLog.error("Error parsing the json '" + json + "'");
                throw ioE;
            }

            return map;
        }

        private Map<String, Object> deserialize(final JsonReader jsonR) throws IOException {

            Map<String, Object> map = new HashMap<>();
            String tempKey;
            Object tempValue;
            JsonToken tempToken;

            jsonR.beginObject();

            // 
            while (jsonR.hasNext()) {

                // get the next key
                tempKey = jsonR.nextName();
                // get the value
                tempToken = jsonR.peek();

                gsonLog.error("TOKEN : " + tempToken);

                if (JsonToken.END_DOCUMENT == tempToken) {
                    //GlobalLogger.info(  );
                    break;
                }

                // check the type of the value
                switch (tempToken) {

                case BEGIN_ARRAY:
                    tempValue = parseArray(jsonR);
                    break;
                case BEGIN_OBJECT:
                    tempValue = parseObject(jsonR);
                    break;
                case BOOLEAN:
                    tempValue = jsonR.nextBoolean();
                    break;
                case NUMBER:
                    tempValue = jsonR.nextDouble();
                    break;
                case STRING:
                    tempValue = jsonR.nextString();
                    break;
                case NULL:
                    tempValue = null;
                    jsonR.nextNull();
                    break;
                default:
                    throw new IllegalStateException("Wrong Token '" + tempToken + "' , while parsing an array");

                }

                map.put(tempKey, tempValue);
            }
            // close the main object
            jsonR.endObject();
            // close the reader
            jsonR.close();
            return map;
        }

    }

    static Collection<Object> parseArray(final JsonReader jsonReader) throws IOException {
        assert null != jsonReader : "DEBUG: The json Reader is null";

        Collection<Object> l = new ArrayList<>();
        JsonToken tok;

        //
        while (jsonReader.hasNext()) {

            tok = jsonReader.peek();
            // we reach the end of this array
            if (JsonToken.END_ARRAY == tok) {
                jsonReader.endArray();
                // return
                break;
            }
            // what token
            switch (tok) {
            // if array/map - parse and append
            case BEGIN_ARRAY:
                l.add(parseArray(jsonReader));
                break;
            case BEGIN_OBJECT:
                l.add(parseObject(jsonReader));
                break;
            // if raw type
            case STRING:
                l.add(jsonReader.nextString());
                break;
            case BOOLEAN:
                l.add(jsonReader.nextBoolean());
                break;
            case NUMBER:
                l.add(jsonReader.nextDouble());
                break;
            // if null , add null and consume
            case NULL:
                l.add(null);
                jsonReader.nextNull();
                break;

            // all other cases are errors
            default:
                throw new IllegalStateException("Wrong Token '" + tok + "' , while parsing an array");
            }
        }

        return l;
    }

    static Map<String, Object> parseObject(final JsonReader jsonReader) throws IOException {

        Map<String, Object> map = new HashMap<>();
        String tempKey;
        JsonToken tok;
        //
        while (jsonReader.hasNext()) {

            // since we want to restore a map we assue a key/value pair
            tempKey = jsonReader.nextName();
            //
            tok = jsonReader.peek();
            // we reach the end of this array
            if (JsonToken.END_ARRAY == tok) {
                jsonReader.endArray();
                // return
                break;
            }
            // what token
            switch (tok) {
            // if array/map - parse and append
            case BEGIN_ARRAY:
                map.put(tempKey, parseArray(jsonReader));
                break;
            case BEGIN_OBJECT:
                map.put(tempKey, parseObject(jsonReader));
                break;
            // if raw type
            case STRING:
                map.put(tempKey, jsonReader.nextString());
                break;
            case BOOLEAN:
                map.put(tempKey, jsonReader.nextBoolean());
                break;
            case NUMBER:
                map.put(tempKey, jsonReader.nextDouble());
                break;
            // if null , add null and consume
            case NULL:
                map.put(tempKey, null);
                jsonReader.nextNull();
                break;

            // all other cases are errors
            default:
                throw new IllegalStateException("Wrong Token '" + tok + "' , while parsing an array");
            }
        }

        return map;
    }

}