/* * eXist Open Source Native XML Database * Copyright (C) 2011 The eXist Project * http://exist-db.org * * This program 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 * of the License, or (at your option) any later version. * * This program 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; if not, write to the Free Software Foundation * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $Id$ */ package org.exist.util.serializer.json; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; public class JSONObject extends JSONNode { protected JSONNode firstChild = null; private boolean asSimpleValue = false; public JSONObject() { super(Type.OBJECT_TYPE, ANONYMOUS_OBJECT); } public JSONObject(String name) { super(Type.OBJECT_TYPE, name); } public JSONObject(String name, boolean asSimpleValue) { super(Type.OBJECT_TYPE, name); this.asSimpleValue = asSimpleValue; } public void addObject(JSONNode node) { JSONNode childNode = findChild(node.getName()); if (childNode == null) { childNode = getLastChild(); if (childNode == null) firstChild = node; else childNode.setNext(node); } else childNode.setNextOfSame(node); } public JSONNode findChild(String nameToFind) { JSONNode nextNode = firstChild; while (nextNode != null) { if (nextNode.getName().equals(nameToFind)) return nextNode; nextNode = nextNode.getNext(); } return null; } public JSONNode getLastChild() { JSONNode nextNode = firstChild; JSONNode currentNode = null; while (nextNode != null) { currentNode = nextNode; nextNode = currentNode.getNext(); } return currentNode; } public int getChildCount() { int count = 0; JSONNode nextNode = firstChild; while (nextNode != null) { count++; nextNode = nextNode.getNext(); } return count; } public void serialize(Writer writer, boolean isRoot) throws IOException { if (!isRoot && isNamed()) { writer.write('"'); writer.write(getName()); writer.write("\" : "); } if (getNextOfSame() != null || getSerializationType() == SerializationType.AS_ARRAY) { writer.write("["); JSONNode next = this; while (next != null) { next.serializeContent(writer); next = next.getNextOfSame(); if (next != null) writer.write(", "); } writer.write("]"); } else serializeContent(writer); } public void serializeContent(Writer writer) throws IOException { if (firstChild == null) // an empty node gets a null value writer.write("null"); else if (firstChild.getNext() == null && ( firstChild.getType() == Type.VALUE_TYPE || (firstChild.isArray() && !firstChild.isNamed()) ) ) // if there's only one child and if it is text, it is serialized as simple value firstChild.serialize(writer, false); else { // complex object writer.write("{ "); JSONNode next = firstChild; boolean allowText = false; boolean skipMixedContentText = false; while (next != null) { if (next.getType() == Type.VALUE_TYPE) { // if an element has attributes and text content, the text // node is serialized as property "#text". // Text in mixed content nodes is ignored though. if (allowText) { writer.write("\"#text\" : "); next.serialize(writer, false); allowText = false; } else { //writer.write("\"#mixed-content-text\" : "); skipMixedContentText = true; } } else next.serialize(writer, false); if (next.getType() == Type.SIMPLE_PROPERTY_TYPE) allowText = true; next = next.getNext(); if (next != null && !skipMixedContentText && !isMixedContentTextLast(next, allowText)) { writer.write(", "); } skipMixedContentText = false; } writer.write(" }"); } } private boolean isMixedContentTextLast(final JSONNode node, final boolean allowText) { if (node.getType() == Type.VALUE_TYPE && !allowText && node.equals(getLastChild())) return true; return false; } @Override public String toString() { StringWriter writer = new StringWriter(); try { serialize(writer, false); } catch (IOException e) { e.printStackTrace(); } return writer.toString(); } }