Java tutorial
/* * 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; } }