Java tutorial
package com.doitnext.swing.widgets.json; import java.util.Enumeration; import java.util.Iterator; import java.util.Map.Entry; import javax.swing.tree.DefaultMutableTreeNode; import org.apache.commons.lang3.StringUtils; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; /** * <p>Provides the model for translating JsonElement into JTree data nodes. This class is not thread safe.</p> * * @author Stephen Owens * * <p>Provides the model for translating JsonElement into JTree data nodes.</p> * * <p> * Copyright 2011 Stephen P. Owens : steve@doitnext.com * </p> * <p> * 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 * </p> * <p> * http://www.apache.org/licenses/LICENSE-2.0 * </p> * <p> * 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. * </p> */ public class JSONJTreeNode extends DefaultMutableTreeNode { /** * Using default serial id. */ private static final long serialVersionUID = 1L; public enum DataType { ARRAY, OBJECT, VALUE }; final DataType dataType; final int index; String fieldName; final String value; /** * Returns the data type of the node. * @return Value in the enumerated series of possible data types. */ public DataType getDataType() { return dataType; } /** * In case of a property, it has a name. * @return Name of the property. */ public String getFieldName() { return fieldName; } /** * In case of a property, it has a value. * @return Value of the property. */ public String getValue() { return value; } /** * @param fieldName - name of field if applicable or null * @param index - index of element in the array or -1 if not part of an array * @param jsonElement - element to represent */ public JSONJTreeNode(String fieldName, int index, JsonElement jsonElement) { this.index = index; this.fieldName = fieldName; if (jsonElement.isJsonArray()) { this.dataType = DataType.ARRAY; this.value = jsonElement.toString(); populateChildren(jsonElement); } else if (jsonElement.isJsonObject()) { this.dataType = DataType.OBJECT; this.value = jsonElement.toString(); populateChildren(jsonElement); } else if (jsonElement.isJsonPrimitive()) { this.dataType = DataType.VALUE; this.value = jsonElement.toString(); } else if (jsonElement.isJsonNull()) { this.dataType = DataType.VALUE; this.value = jsonElement.toString(); } else { throw new IllegalArgumentException("jsonElement is an unknown element type."); } } private void populateChildren(JsonElement myJsonElement) { switch (dataType) { case ARRAY: int index = 0; Iterator<JsonElement> it = myJsonElement.getAsJsonArray().iterator(); while (it.hasNext()) { JsonElement element = it.next(); JSONJTreeNode childNode = new JSONJTreeNode(null, index, element); this.add(childNode); index++; } break; case OBJECT: for (Entry<String, JsonElement> entry : myJsonElement.getAsJsonObject().entrySet()) { JSONJTreeNode childNode = new JSONJTreeNode(entry.getKey(), -1, entry.getValue()); this.add(childNode); } break; default: throw new IllegalStateException("Internal coding error this should never happen."); } } public JsonElement asJsonElement() { StringBuilder sb = new StringBuilder(); buildJsonString(sb); String json = sb.toString().trim(); if (json.startsWith("{") || json.startsWith("[")) return new JsonParser().parse(sb.toString()); else { // Safety check the JSON, if it is of a named value object // We cheat a little if it is an orphan name value pair then // if we wrap it in {} chars it will parse if it isn't the parse // fails. String testValue = "{" + json + "}"; try { JsonElement wrapperElt = new JsonParser().parse(testValue); JsonObject obj = (JsonObject) wrapperElt; Iterator<Entry<String, JsonElement>> it = obj.entrySet().iterator(); Entry<String, JsonElement> entry = it.next(); return entry.getValue(); } catch (JsonSyntaxException jse) { JsonElement rawElement = new JsonParser().parse(json); return rawElement; } } } @SuppressWarnings("unchecked") private void buildJsonString(StringBuilder sb) { if (!StringUtils.isEmpty(this.fieldName)) { sb.append("\"" + this.fieldName + "\":"); } Enumeration children; switch (dataType) { case ARRAY: sb.append("["); children = this.children(); while (children.hasMoreElements()) { JSONJTreeNode child = (JSONJTreeNode) children.nextElement(); child.buildJsonString(sb); if (children.hasMoreElements()) sb.append(","); } sb.append("]"); break; case OBJECT: sb.append("{"); children = this.children(); while (children.hasMoreElements()) { JSONJTreeNode child = (JSONJTreeNode) children.nextElement(); child.buildJsonString(sb); if (children.hasMoreElements()) sb.append(","); } sb.append("}"); break; default: { // Use the JSON parser to parse the value for safety JsonElement elt = new JsonParser().parse(this.value); sb.append(elt.toString()); } } } @Override public String toString() { switch (dataType) { case ARRAY: case OBJECT: if (index >= 0) { return String.format("[%d] (%s)", index, dataType.name()); } else if (fieldName != null) { return String.format("%s (%s)", fieldName, dataType.name()); } else { return String.format("(%s)", dataType.name()); } default: if (index >= 0) { return String.format("[%d] %s", index, value); } else if (fieldName != null) { return String.format("%s: %s", fieldName, value); } else { return String.format("%s", value); } } } }