org.apache.wink.json4j.JSONObject Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.wink.json4j;
import java.io.BufferedWriter;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import org.apache.wink.json4j.internal.BeanSerializer;
import org.apache.wink.json4j.internal.Null;
import org.apache.wink.json4j.internal.Parser;
import org.apache.wink.json4j.internal.Serializer;
import org.apache.wink.json4j.internal.SerializerVerbose;
/**
* Models a JSON Object.
*
* Extension of HashMap that only allows String keys, and values which are JSON-able (such as a Java Bean).
*
* JSON-able values are: null, and instances of String, Boolean, Number, JSONObject and JSONArray.
*
* Instances of this class are not thread-safe.
*/
public class JSONObject extends HashMap implements JSONArtifact {
private static final long serialVersionUID = -3269263069889337298L;
/**
* A constant definition reference to Java null.
* Provided for API compatibility with other JSON parsers.
*/
public static final Object NULL = new Null();
/**
* Return whether the object is a valid value for a property.
* @param object The object to check for validity as a JSON property value.
* @return boolean indicating if the provided object is directly convertable to JSON.
*/
public static boolean isValidObject(Object object) {
if (null == object) return true;
return isValidType(object.getClass());
}
/**
* Return whether the class is a valid type of value for a property.
* @param clazz The class type to check for validity as a JSON object type.
* @return boolean indicating if the provided class is directly convertable to JSON.
*/
public static boolean isValidType(Class clazz) {
if (null == clazz) throw new IllegalArgumentException();
if (String.class == clazz) return true;
if (Boolean.class == clazz) return true;
if (JSONObject.class.isAssignableFrom(clazz)) return true;
if (JSONArray.class == clazz) return true;
if (Number.class.isAssignableFrom(clazz)) return true;
if (JSONString.class.isAssignableFrom(clazz)) return true;
return false;
}
/**
* Create a new instance of this class.
*/
public JSONObject() {
super();
}
/**
* Create a new instance of this class taking selected values from the underlying one. If a key is not
* found, then it will be copied into the new JSONObject.
* @param obj The JSONObject to extract values from.
* @param keys The keys to take from the JSONObject and apply to this instance.
* @throws JSONException Thrown if a key is duplicated in the string[] keys
*/
public JSONObject(JSONObject obj, String[] keys) throws JSONException{
super();
if (keys != null && keys.length > 0) {
for (int i = 0; i < keys.length; i++) {
if (this.containsKey(keys[i])) {
throw new JSONException("Duplicate key: " + keys[i]);
}
try {
Object item = obj.opt(keys[i]);
if (item != null) {
this.put(keys[i], item);
}
} catch (Exception ex) {
JSONException jex = new JSONException("Error occurred during JSONObject creation");
jex.initCause(ex);
throw jex;
}
}
}
}
/**
* Create a new instance of this class from the provided JSON object string.
* Note: This is the same as new JSONObject(str, false); Parsing in non-strict mode.
* @param str The JSON string to parse.
* @throws JSONException Thrown when the string passed is null, or malformed JSON..
*/
public JSONObject(String str) throws JSONException {
super();
StringReader reader = new StringReader(str);
(new Parser(reader)).parse(this);
}
/**
* Create a new instance of this class from the provided JSON object string.
* @param str The JSON string to parse.
* @param strict Whether or not to parse in 'strict' mode, meaning all strings must be quoted (including identifiers), and comments are not allowed.
* @throws JSONException Thrown when the string passed is null, or malformed JSON..
*/
public JSONObject(String str, boolean strict) throws JSONException {
super();
StringReader reader = new StringReader(str);
(new Parser(reader, strict)).parse(this);
}
/**
* Create a new instance of this class from the data provided from the reader. The reader content must be a JSON object string.
* Note: The reader will not be closed, that is left to the caller.
* Note: This is the same as new JSONObject(rdr, false); Parsing in non-strict mode.
* @throws JSONException Thrown when the string passed is null, or malformed JSON..
*/
public JSONObject(Reader rdr) throws JSONException {
(new Parser(rdr)).parse(this);
}
/**
* Create a new instance of this class from the data provided from the reader. The reader content must be a JSON object string.
* Note: The reader will not be closed, that is left to the caller.
* @param rdr The reader from which to read the JSON.
* @param strict Whether or not to parse in 'strict' mode, meaning all strings must be quoted (including identifiers), and comments are not allowed.
* @throws JSONException Thrown when the string passed is null, or malformed JSON..
*/
public JSONObject(Reader rdr, boolean strict) throws JSONException {
(new Parser(rdr, strict)).parse(this);
}
/**
* Create a new instance of this class from the data provided from the input stream. The stream content must be a JSON object string.
* Note: The input stream content is assumed to be UTF-8 encoded.
* Note: The InputStream will not be closed, that is left to the caller.
* Note: This is the same as new JSONObject(is, false); Parsing in non-strict mode.
* @param is The InputStream from which to read the JSON.
* @throws JSONException Thrown when the string passed is null, or malformed JSON..
*/
public JSONObject (InputStream is) throws JSONException {
InputStreamReader isr = null;
if (is != null) {
try {
isr = new InputStreamReader(is, "UTF-8");
} catch (Exception ex) {
isr = new InputStreamReader(is);
}
} else {
throw new JSONException("InputStream cannot be null");
}
(new Parser(isr)).parse(true, this);
}
/**
* Create a new instance of this class from the data provided from the input stream. The stream content must be a JSON object string.
* Note: The input stream content is assumed to be UTF-8 encoded.
* Note: The InputStream will not be closed, that is left to the caller.
* @param is The InputStream from which to read the JSON.
* @param strict Whether or not to parse in 'strict' mode, meaning all strings must be quoted (including identifiers), and comments are not allowed.
* @throws JSONException Thrown when the string passed is null, or malformed JSON..
*/
public JSONObject (InputStream is, boolean strict) throws JSONException {
InputStreamReader isr = null;
if (is != null) {
try {
isr = new InputStreamReader(is, "UTF-8");
} catch (Exception ex) {
isr = new InputStreamReader(is);
}
} else {
throw new JSONException("InputStream cannot be null");
}
(new Parser(isr, strict)).parse(true, this);
}
/**
* Create a new instance of this class using the contents of the provided map.
* The contents of the map should be values considered JSONable.
* It will try to convert JavaBeans in the map to JSONObjects if possible.
* @param map The map of key/value pairs to insert into this JSON object
*/
public JSONObject(Map map) {
super();
Set set = map.keySet();
if (set != null) {
Iterator itr = set.iterator();
if (itr != null) {
while (itr.hasNext()) {
Object key = itr.next();
String sKey = key.toString();
try {
this.put(sKey, map.get(key));
} catch (Exception ex) {
//Squelch to match other model behavior.
}
}
}
}
}
/**
* Create a new instance of this class using the properties of the provided JavaBean.
* The bean is converted to a JSONObject via reflection of getter methods.
* @param javaBean A java bean with getters for properties.
* @throws JSONException Thrown when contents in the map cannot be made JSONable.
* @throws NullPointerException Thrown if the map is null, or a key in the map is null..
*/
public JSONObject(Object javaBean) throws JSONException {
super();
if (javaBean != null) {
JSONObject map = (JSONObject)BeanSerializer.toJson(javaBean, true);
this.putAll(map);
}
}
/**
* Create a new instance of this class using the properties of the provided JavaBean.
* The bean is converted to a JSONObject via reflection of getter methods.
* @param javaBean A java bean with getters for properties.
* @param includeSuperclass Boolean indicating that if the object is a JavaBean, include superclass getter properties.
* @throws JSONException Thrown when contents in the map cannot be made JSONable.
* @throws NullPointerException Thrown if the map is null, or a key in the map is null..
*/
public JSONObject(Object javaBean, boolean includeSuperclass) throws JSONException {
super();
if (javaBean != null) {
JSONObject map = (JSONObject)BeanSerializer.toJson(javaBean, includeSuperclass);
this.putAll(map);
}
}
/**
* Create a new instance of this class using the contents of the provided map.
* The contents of the map should be values considered JSONable.
* @param map The map of key/value pairs to insert into this JSON object
* @param includeSuperclass For values of the map which are JavaBeans, include superclass getter properties.
* @throws JSONException Thrown when contents in the map cannot be made JSONable.
* @throws NullPointerException Thrown if the map is null, or a key in the map is null..
*/
public JSONObject(Map map, boolean includeSuperclass) throws JSONException {
super();
Set set = map.keySet();
if (set != null) {
Iterator itr = set.iterator();
if (itr != null) {
while (itr.hasNext()) {
Object key = itr.next();
String sKey = key.toString();
this.put(sKey, map.get(key), includeSuperclass);
}
}
}
}
/**
* Write this object to the stream as JSON text in UTF-8 encoding. Same as calling write(os,false);
* Note that encoding is always written as UTF-8, as per JSON spec.
* @param os The output stream to write data to.
*
* @throws JSONException Thrown on IO errors during serialization.
*/
public OutputStream write(OutputStream os) throws JSONException {
write(os,false);
return os;
}
/**
* Convert this object into a stream of JSON text. Same as calling write(writer,false);
* Note that encoding is always written as UTF-8, as per JSON spec.
* @param os The output stream to write data to.
* @param verbose Whether or not to write the JSON text in a verbose format.
*
* @throws JSONException Thrown on IO errors during serialization.
*/
public OutputStream write(OutputStream os, boolean verbose) throws JSONException {
Writer writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
} catch (UnsupportedEncodingException uex) {
JSONException jex = new JSONException(uex.toString());
jex.initCause(uex);
throw jex;
}
write(writer, verbose);
try {
writer.flush();
} catch (Exception ex) {
JSONException jex = new JSONException("Error during buffer flush");
jex.initCause(ex);
throw jex;
}
return os;
}
/**
* Write this object to the stream as JSON text in UTF-8 encoding, specifying how many spaces should be used for each indent.
* @param indentDepth How many spaces to use for each indent level. Should be one to eight.
* Less than one means no intending, greater than 8 and it will just use tab.
*
* @throws JSONException Thrown on IO errors during serialization.
*/
public OutputStream write(OutputStream os, int indentDepth) throws JSONException {
Writer writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
} catch (UnsupportedEncodingException uex) {
JSONException jex = new JSONException(uex.toString());
jex.initCause(uex);
throw jex;
}
write(writer, indentDepth);
try {
writer.flush();
} catch (Exception ex) {
JSONException jex = new JSONException("Error during buffer flush");
jex.initCause(ex);
throw jex;
}
return os;
}
/**
* Write this object to the writer as JSON text. Same as calling write(writer,false);
* @param writer The writer which to write the JSON text to.
*
* @throws JSONException Thrown on IO errors during serialization.
*/
public Writer write(Writer writer) throws JSONException {
write(writer, false);
return writer;
}
/**
* Write this object to the writer as JSON text in UTF-8 encoding, specifying whether to use verbose (tab-indented) output or not.
* @param writer The writer which to write the JSON text to.
*
* @throws JSONException Thrown on IO errors during serialization.
*/
public Writer write(Writer writer, boolean verbose) throws JSONException {
Serializer serializer;
//Try to avoid double-buffering or buffering in-memory
//writers.
Class writerClass = writer.getClass();
boolean flushIt = false;
if (!StringWriter.class.isAssignableFrom(writerClass) &&
!CharArrayWriter.class.isAssignableFrom(writerClass) &&
!BufferedWriter.class.isAssignableFrom(writerClass)) {
writer = new BufferedWriter(writer);
flushIt = true;
}
if (verbose) {
serializer = new SerializerVerbose(writer);
} else {
serializer = new Serializer(writer);
}
try {
serializer.writeObject(this);
} catch (IOException iox) {
JSONException jex = new JSONException("Error occurred during input read.");
jex.initCause(iox);
throw jex;
}
if (flushIt) {
try {
writer.flush();
} catch (Exception ex) {
JSONException jex = new JSONException("Error during buffer flush");
jex.initCause(ex);
throw jex;
}
}
return writer;
}
/**
* Write this object to the writer as JSON text, specifying how many spaces should be used for each indent.
* This is an alternate indent style to using tabs.
* @param writer The writer which to write the JSON text to.
* @param indentDepth How many spaces to use for each indent. The value should be between one to eight.
*/
public Writer write(Writer writer, int indentDepth) throws JSONException {
Serializer serializer;
if (indentDepth < 1) {
indentDepth = 0;
} else if (indentDepth > 8) {
indentDepth = 9;
}
//Try to avoid double-buffering or buffering in-memory
//writers.
Class writerClass = writer.getClass();
boolean flushIt = false;
if (!StringWriter.class.isAssignableFrom(writerClass) &&
!CharArrayWriter.class.isAssignableFrom(writerClass) &&
!BufferedWriter.class.isAssignableFrom(writerClass)) {
writer = new BufferedWriter(writer);
flushIt = true;
}
if (indentDepth > 0) {
serializer = new SerializerVerbose(writer, indentDepth);
} else {
serializer = new Serializer(writer);
}
try {
serializer.writeObject(this);
} catch (IOException iox) {
JSONException jex = new JSONException("Error occurred during input read.");
jex.initCause(iox);
throw jex;
}
if (flushIt) {
try {
writer.flush();
} catch (Exception ex) {
JSONException jex = new JSONException("Error during buffer flush");
jex.initCause(ex);
throw jex;
}
}
return writer;
}
/**
* Convert this object into a String of JSON text, specifying how many spaces should be used for each indent.
* This is an alternate indent style to using tabs.
* @param indentDepth How many spaces to use for each indent. The value should be between one to eight.
* Less than one means no indenting, greater than 8 and it will just use tab.
*
* @throws JSONException Thrown on errors during serialization.
*/
public String write(int indentDepth) throws JSONException {
Serializer serializer;
StringWriter writer = new StringWriter();
if (indentDepth < 1) {
indentDepth = 0;
} else if (indentDepth > 8) {
indentDepth = 9;
}
if (indentDepth > 0) {
serializer = new SerializerVerbose(writer, indentDepth);
} else {
serializer = new Serializer(writer);
}
try {
serializer.writeObject(this).flush();
} catch (IOException iox) {
JSONException jex = new JSONException("Error occurred during write.");
jex.initCause(iox);
throw jex;
}
return writer.toString();
}
/**
* Convert this object into a String of JSON text, specifying whether to use verbose (tab-indented) output or not.
* @param verbose Whether or not to write in compressed format.
*
* @throws JSONException Thrown on errors during serialization.
*/
public String write(boolean verbose) throws JSONException {
Serializer serializer;
StringWriter writer = new StringWriter();
if (verbose) {
serializer = new SerializerVerbose(writer);
} else {
serializer = new Serializer(writer);
}
try {
serializer.writeObject(this).flush();
} catch (IOException iox) {
JSONException jex = new JSONException("Error occurred during write.");
jex.initCause(iox);
throw jex;
}
return writer.toString();
}
/**
* Convert this object into a String of JSON text. Same as write(false);
*
* @throws JSONException Thrown on IO errors during serialization.
*/
public String write() throws JSONException {
return write(false);
}
/**
* Method to obtain the object value for a key.
* This string-based method is provided for API compatibility to other JSON models.
* @param key The key (attribute) name to obtain the value for.
* @throws JSONException Thrown if the noted key is not in the map of key/value pairs.
*/
public Object get(String key) throws JSONException {
Object val = this.get((Object)key);
if (val == null) {
if (!this.containsKey(key)) {
throw new JSONException("The key [" + key + "] was not in the map");
}
}
return val;
}
/**
* Method to obtain the object value for a key. If the key is not in the map, null is returned.
* This string-based method is provided for API compatibility to other JSON models.
* @param key The key (attribute) name to obtain the value for.
*/
public Object opt(String key) {
return this.get((Object)key);
}
/**
* (non-Javadoc)
* @see java.util.HashMap#put(java.lang.Object, java.lang.Object)
* @param key The key to put in the JSONObject
* @param value The value to put in the JSONObject
* @param includeSuperclass Boolean indicating that if the object is a JavaBean, include superclass getter properties.
* @throws JSONException. Thrown if key is null, not a string, or the value could not be converted.
*/
public Object put(Object key, Object value, boolean includeSuperclass) throws JSONException{
if (null == key) throw new JSONException("key must not be null");
if (!(key instanceof String)) throw new JSONException("key must be a String");
if (!isValidObject(value)) {
// Try to convert the unknown type to a JSONObject
if (value != null ) {
try {
value = BeanSerializer.toJson(value, includeSuperclass);
} catch (Exception ex) {
throw new JSONException("Invalid type of value. Could not convert type: [" + value.getClass().getName() + "]");
}
}
}
return super.put(key, value);
}
/**
* (non-Javadoc)
* @see java.util.HashMap#put(java.lang.Object, java.lang.Object)
* This is the same as calling put(key, value, true);
*/
public Object put(Object key, Object value) {
try {
return put(key, value, true);
} catch (Exception e) {
IllegalArgumentException iae = new IllegalArgumentException("Error occurred during JSON conversion");
iae.initCause(e);
throw iae;
}
}
/**
* Convenience functions, to help map from other JSON parsers.
*/
/**
* Similar to default HashMap put, except it returns JSONObject instead of Object.
* @see java.util.HashMap#put(java.lang.Object, java.lang.Object)
* @return A reference to this object instance.
* @throws JSONException. Thrown if key is null, not a string, or the value could not be converted to JSON.
*/
public JSONObject put(String key, Object value) throws JSONException{
this.put((Object)key, value);
return this;
}
/**
* Method to add an atomic boolean to the JSONObject.
* param key The key/attribute name to set the boolean at.
* @param value The boolean value.
* @throws JSONException. Thrown if key is null or not a string.
* @return A reference to this object instance.
*/
public JSONObject put(String key, boolean value) throws JSONException{
this.put(key,new Boolean(value));
return this;
}
/**
* Method to add an atomic double to the JSONObject.
* param key The key/attribute name to set the double at.
* @param value The double value.
* @throws JSONException. Thrown if key is null or not a string.
* @return A reference to this object instance.
*/
public JSONObject put(String key, double value) throws JSONException{
this.put(key, new Double(value));
return this;
}
/**
* Method to add an atomic integer to the JSONObject.
* param key The key/attribute name to set the integer at.
* @param value The integer value.
* @throws JSONException. Thrown if key is null or not a string.
* @return A reference to this object instance.
*/
public JSONObject put(String key, int value) throws JSONException{
this.put(key, new Integer(value));
return this;
}
/**
* Method to add an atomic short to the JSONObject.
* param key The key/attribute name to set the integer at.
* @param value The integer value.
* @throws JSONException. Thrown if key is null or not a string.
* @return A reference to this object instance.
*/
public JSONObject put(String key, short value) throws JSONException{
this.put(key, new Short(value));
return this;
}
/**
* Method to add an atomic long to the JSONObject.
* @param key The key/attribute name to set the long to.
* @param value The long value.
* @throws JSONException. Thrown if key is null or not a string.
* @return A reference to this object instance.
*/
public JSONObject put(String key, long value) throws JSONException{
this.put(key, new Long(value));
return this;
}
/**
* Method to add a Map as a new JSONObject contained in this JSONObject
* @param key The key/attribute name to set the new JSONObject to.
* @param value The Map object to convert to a JSONObject and store.
* @param includeSuperclass For values of the map which are JavaBeans and are converted, include superclass getter properties.
* @throws JSONException Thrown when contents in the map cannot be converted to something JSONable.
* @return A reference to this object instance.
*/
public JSONObject put(String key, Map value, boolean includeSuperclass) throws JSONException {
if (value == null) {
this.put(key, (Object)null);
} else {
if (JSONObject.class.isAssignableFrom(value.getClass())) {
this.put(key, (Object)value);
} else {
this.put(key, new JSONObject(value, includeSuperclass));
}
}
return this;
}
/**
* Method to add a Map as a new JSONObject contained in this JSONObject
* Same as calling put(String, Map, true);
* @param key The key/attribute name to set the new JSONObject to.
* @param value The Map object to convert to a JSONObject and store.
* @throws JSONException Thrown when contents in the map cannot be converted to something JSONable.
* @return A reference to this object instance.
*/
public JSONObject put(String key, Map value) throws JSONException {
return put(key,value,true);
}
/**
* Method to add a Collection as a new JSONArray contained in this JSONObject
* @param key The key/attribute name to set the collection to.
* @param value The Map object to convert to a JSONObject and store.
* @param includeSuperclass For values of the map which are JavaBeans and are converted, include superclass getter properties.
* @throws JSONException Thrown when contents in the Collection cannot be converted to something JSONable.
* @return A reference to this object instance.
*/
public JSONObject put(String key, Collection value, boolean includeSuperclass) throws JSONException {
if (value == null) {
this.put(key, (Object)null);
} else {
if (JSONArray.class.isAssignableFrom(value.getClass())) {
this.put(key, (Object)value);
} else {
this.put(key, new JSONArray(value, includeSuperclass));
}
}
return this;
}
/**
* Method to add a Collection as a new JSONArray contained in this JSONObject
* @param key The key/attribute name to set the collection to.
* @param value The Map object to convert to a JSONObject and store.
* @throws JSONException Thrown when contents in the Collection cannot be converted to something JSONable.
* @return A reference to this object instance.
*/
public JSONObject put(String key, Collection value) throws JSONException {
return put(key,value,true);
}
/**
* Method to add an Object array as a new JSONArray contained in this JSONObject
* @param key The key/attribute name to set the collection to.
* @param value The Object array to convert to a JSONArray and store.
* @throws JSONException Thrown when contents in the Collection cannot be converted to something JSONable.
* @return A reference to this object instance.
*/
public JSONObject put(String key, Object[] value) throws JSONException {
return put (key, new JSONArray(value), true);
}
/**
* Method to add an Object array as a new JSONArray contained in this JSONObject
* @param key The key/attribute name to set the collection to.
* @param value The Object array to convert to a JSONArray and store.
* @param includeSuperclass For values of the Object array which are JavaBeans and are converted, include superclass getter properties.
* @throws JSONException Thrown when contents in the Collection cannot be converted to something JSONable.
* @return A reference to this object instance.
*/
public JSONObject put(String key, Object[] value, boolean includeSuperclass) throws JSONException {
return put (key, new JSONArray(value), includeSuperclass);
}
/**
* Utility method to obtain the specified key as a 'boolean' value
* Only boolean true, false, and the String true and false will return. In this case null, the number 0, and empty string should be treated as false.
* everything else is true.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* throws JSONException Thrown when the type returned by get(key) is not a boolean instance, or the strings 'true' or 'false'.
* @return A boolean value (true or false), if the value stored for key is a Boolean, or the strings 'true' or 'false'.
*/
public boolean getBoolean(String key) throws JSONException {
Object val = this.opt(key);
if (val != null) {
if (val instanceof Boolean) {
return((Boolean)val).booleanValue();
} else if (Number.class.isAssignableFrom(val.getClass())) {
throw new JSONException("Value at key: [" + key + "] was not a boolean or string value of 'true' or 'false'.");
} else if (String.class.isAssignableFrom(val.getClass())) {
String str = (String)val;
if (str.equals("true")) {
return true;
} else if (str.equals("false")) {
return false;
} else {
throw new JSONException("The value for key: [" + key + "]: [" + str + "] was not 'true' or 'false'");
}
} else {
throw new JSONException("The value for key: [" + key + "] was not a type that can be converted to boolean");
}
} else {
throw new JSONException("The value for key: [" + key + "] was null");
}
}
/**
* Utility method to obtain the specified key as a 'boolean' value
* Only returns true if the value is boolean true or the string 'true'. All other values return false.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* @return A boolean value (true or false), if the value stored for key is a Boolean, or the strings 'true' or 'false'.
*/
public boolean optBoolean(String key) {
Object val = this.opt(key);
if (val != null) {
if (val instanceof Boolean) {
return((Boolean)val).booleanValue();
} else if (Number.class.isAssignableFrom(val.getClass())) {
return false;
} else if (String.class.isAssignableFrom(val.getClass())) {
String str = (String)val;
if (str.equals("true")) {
return true;
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
}
/**
* Utility method to obtain the specified key as a 'boolean' value
* Only returns true if the value is boolean true or the string 'true'. All other values return false.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* @param defaultValue The default value to return.
* @return A boolean value (true or false), if the value stored for key is a Boolean, or the strings 'true' or 'false'.
*/
public boolean optBoolean(String key, boolean defaultValue) {
Object val = this.opt(key);
if (val != null) {
if (val instanceof Boolean) {
return((Boolean)val).booleanValue();
} else if (Number.class.isAssignableFrom(val.getClass())) {
return false;
} else if (String.class.isAssignableFrom(val.getClass())) {
String str = (String)val;
if (str.equals("true")) {
return true;
} else if (str.equals("false")) {
return false;
} else {
return defaultValue;
}
} else {
return defaultValue;
}
} else {
return defaultValue;
}
}
/**
* Utility method to obtain the specified key as a 'double' value
* Only values of Number will be converted to double, all other types will generate an exception
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* throws JSONException Thrown when the type returned by get(key) is not a Double instance, or cannot be converted to a double.
* @return A double value if the value stored for key is an instance of Number.
*/
public double getDouble(String key) throws JSONException {
Object val = this.opt(key);
if (val != null) {
if (Number.class.isAssignableFrom(val.getClass())) {
return((Number)val).doubleValue();
} else {
throw new JSONException("The value for key: [" + key + "] was not a type that can be converted to double");
}
} else {
throw new JSONException("The value for key: [" + key + "] was null. Number required.");
}
}
/**
* Utility method to obtain the specified key as a 'double' value
* Only values of Number will be converted to double. all other values will return Double.NaN.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* @return A double value if the value stored for key is an instance of Number.
*/
public double optDouble(String key) {
Object val = this.opt(key);
if (val != null) {
if (Number.class.isAssignableFrom(val.getClass())) {
return((Number)val).doubleValue();
}
}
return Double.NaN;
}
/**
* Utility method to obtain the specified key as a 'double' value
* Only values of Number will be converted to double. all other values will return Double.NaN.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* @param defaultValue The default double value to return in case of NaN/null values in map.
* @return A double value if the value stored for key is an instance of Number.
*/
public double optDouble(String key, double defaultValue) {
Object val = this.opt(key);
if (val != null) {
if (Number.class.isAssignableFrom(val.getClass())) {
return((Number)val).doubleValue();
}
}
return defaultValue;
}
/**
* Utility method to obtain the specified key as a 'short' value
* Only values of Number will be converted to short, all other types will generate an exception.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* throws JSONException Thrown when the type returned by get(key) is not a Short instance, or cannot be converted to a short.
* @return A short value if the value stored for key is an instance of Number.
*/
public short getShort(String key) throws JSONException {
Object val = this.opt(key);
if (val != null) {
if (Number.class.isAssignableFrom(val.getClass())) {
return((Number)val).shortValue();
} else {
throw new JSONException("The value for key: [" + key + "] was not a type that can be converted to short");
}
} else {
throw new JSONException("The value for key: [" + key + "] was null. Number required.");
}
}
/**
* Utility method to obtain the specified key as a 'short' value
* Only values of Number will be converted to short. All other types return 0.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* @return A short value if the value stored for key is an instance of Number. 0 otherwise.
*/
public short optShort(String key) {
Object val = this.opt(key);
if (val != null) {
if (Number.class.isAssignableFrom(val.getClass())) {
return((Number)val).shortValue();
}
}
return(short)0;
}
/**
* Utility method to obtain the specified key as a 'short' value
* Only values of Number will be converted to short.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* @param defaultValue The default value to return in the case of null/nonNumber values in the map.
* @return A short value if the value stored for key is an instance of Number. 0 otherwise.
*/
public short optShort(String key, short defaultValue) {
Object val = this.opt(key);
if (val != null) {
if (Number.class.isAssignableFrom(val.getClass())) {
return((Number)val).shortValue();
}
}
return defaultValue;
}
/**
* Utility method to obtain the specified key as a 'int' value
* Only values of Number will be converted to integer, all other types will generate an exception.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* throws JSONException Thrown when the type returned by get(key) is not a Double instance, or cannot be converted to a double.
* @return A int value if the value stored for key is an instance of Number.
*/
public int getInt(String key) throws JSONException {
Object val = this.opt(key);
if (val != null) {
if (Number.class.isAssignableFrom(val.getClass())) {
return((Number)val).intValue();
} else {
throw new JSONException("The value for key: [" + key + "] was not a type that can be converted to integer");
}
} else {
throw new JSONException("The value for key: [" + key + "] was null. Number required.");
}
}
/**
* Utility method to obtain the specified key as a 'int' value
* Provided for compatibility to other JSON models.
* Only values of Number will be converted to integer, all other types will return 0.
* @param key The key to look up.
* @return A int value if the value stored for key is an instance of Number. 0 otherwise.
*/
public int optInt(String key) {
Object val = this.opt(key);
if (val != null) {
if (Number.class.isAssignableFrom(val.getClass())) {
return((Number)val).intValue();
}
}
return 0;
}
/**
* Utility method to obtain the specified key as a 'int' value
* Provided for compatibility to other JSON models.
* Only values of Number will be converted to integer
* @param key The key to look up.
* @param defaultValue The default int value to return in case of null/non-number values in the map.
* @return A int value if the value stored for key is an instance of Number.
*/
public int optInt(String key, int defaultValue) {
Object val = this.opt(key);
if (val != null) {
if (Number.class.isAssignableFrom(val.getClass())) {
return((Number)val).intValue();
}
}
return defaultValue;
}
/**
* Utility method to obtain the specified key as a 'long' value
* Only values of Number will be converted to long, all other types will generate an exception.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* throws JSONException Thrown when the type returned by get(key) is not a Long instance, or cannot be converted to a long..
* @return A long value if the value stored for key is an instance of Number.
*/
public long getLong(String key) throws JSONException {
Object val = this.opt(key);
if (val != null) {
if (Number.class.isAssignableFrom(val.getClass())) {
return((Number)val).longValue();
} else {
throw new JSONException("The value for key: [" + key + "] was not a type that can be converted to long");
}
} else {
throw new JSONException("The value for key: [" + key + "] was null. Number required.");
}
}
/**
* Utility method to obtain the specified key as a 'long' value
* Only values of Number will be converted to long. all other types return 0.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* @return A long value if the value stored for key is an instance of Number, 0 otherwise.
*/
public long optLong(String key) throws JSONException {
Object val = this.opt(key);
if (val != null) {
if (Number.class.isAssignableFrom(val.getClass())) {
return((Number)val).longValue();
}
}
return(long)0;
}
/**
* Utility method to obtain the specified key as a 'long' value
* Only values of Number will be converted to long. all other types return 0.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* @param defaultValue The default long value to return in case of null/non Number values in the map.
* @return A long value if the value stored for key is an instance of Number, defaultValue otherwise.
*/
public long optLong(String key, long defaultValue) throws JSONException {
Object val = this.opt(key);
if (val != null) {
if (Number.class.isAssignableFrom(val.getClass())) {
return((Number)val).intValue();
}
}
return defaultValue;
}
/**
* Utility method to obtain the specified key as a 'string' value
* Only values that can be easily converted to string will be returned. A null will generate an exception.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* throws JSONException Thrown when the type returned by get(key) is null.
* @return A string value if the value if the value stored for key is not null.
*/
public String getString(String key) throws JSONException {
Object val = this.opt(key);
if (val != null) {
return val.toString();
} else {
throw new JSONException("The value for key: [" + key + "] was null. Object required.");
}
}
/**
* Utility method to obtain the specified key as a 'string' value
* Only values that can be easily converted to string will be returned. A null will generate an exception.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* throws JSONException Thrown when the type returned by get(key) is null.
* @return A string value if the value if the value stored for key is not null.
*/
public String optString(String key) {
Object val = this.opt(key);
if (val != null) {
return val.toString();
}
return null;
}
/**
* Utility method to obtain the specified key as a 'string' value
* Only values that can be easily converted to string will be returned. A null will generate an exception.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* @param defaultValue The default String value to return in the case of null values in the map.
* @return A string value if the value if the value stored for key is not null, defaultValue otherwise.
*/
public String optString(String key, String defaultValue) {
Object val = this.opt(key);
if (val != null) {
return val.toString();
}
return defaultValue;
}
/**
* Utility method to obtain the specified key as a JSONObject
* Only values that are instances of JSONObject will be returned. A null will generate an exception.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* throws JSONException Thrown when the type returned by get(key) is not a JSONObject instance.
* @return A JSONObject value if the value stored for key is an instance or subclass of JSONObject.
*/
public JSONObject getJSONObject(String key) throws JSONException {
Object val = this.opt(key);
if (val != null) {
if (JSONObject.class.isAssignableFrom(val.getClass())) {
return(JSONObject)val;
} else {
throw new JSONException("The value for key: [" + key + "] was not a JSONObject");
}
} else {
throw new JSONException("The value for key: [" + key + "] was null. Object required.");
}
}
/**
* Utility method to obtain the specified key as a JSONObject
* Only values that are instances of JSONObject will be returned. A null will generate an exception.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* @return A JSONObject value if the value stored for key is an instance or subclass of JSONObject, null otherwise.
*/
public JSONObject optJSONObject(String key) {
Object val = this.opt(key);
if (val != null) {
if (JSONObject.class.isAssignableFrom(val.getClass())) {
return(JSONObject)val;
}
}
return null;
}
/**
* Utility method to obtain the specified key as a JSONObject
* Only values that are instances of JSONObject will be returned. A null will generate an exception.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* @param defaultValue The default JSONObject to return in the case of null/non JSONObject values in the map.
* @return A JSONObject value if the value stored for key is an instance or subclass of JSONObject, defaultValue otherwise.
*/
public JSONObject optJSONObject(String key, JSONObject defaultValue) {
Object val = this.opt(key);
if (val != null) {
if (JSONObject.class.isAssignableFrom(val.getClass())) {
return(JSONObject)val;
}
}
return defaultValue;
}
/**
* Utility method to obtain the specified key as a JSONArray
* Only values that are instances of JSONArray will be returned. A null will generate an exception.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* throws JSONException Thrown when the type returned by get(key) is not a Long instance, or cannot be converted to a long..
* @return A JSONArray value if the value stored for key is an instance or subclass of JSONArray.
*/
public JSONArray getJSONArray(String key) throws JSONException {
Object val = this.opt(key);
if (val != null) {
if (JSONArray.class.isAssignableFrom(val.getClass())) {
return(JSONArray)val;
} else {
throw new JSONException("The value for key: [" + key + "] was not a JSONObject");
}
} else {
throw new JSONException("The value for key: [" + key + "] was null. Object required.");
}
}
/**
* Utility method to obtain the specified key as a JSONArray
* Only values that are instances of JSONArray will be returned. A null will generate an exception.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* @return A JSONArray value if the value stored for key is an instance or subclass of JSONArray, null otherwise.
*/
public JSONArray optJSONArray(String key) throws JSONException {
Object val = this.opt(key);
if (val != null) {
if (JSONArray.class.isAssignableFrom(val.getClass())) {
return(JSONArray)val;
}
}
return null;
}
/**
* Utility method to obtain the specified key as a JSONArray
* Only values that are instances of JSONArray will be returned. A null will generate an exception.
* Provided for compatibility to other JSON models.
* @param key The key to look up.
* @param defaultValue The default value to return if the value in the map is null/not a JSONArray.
* @return A JSONArray value if the value stored for key is an instance or subclass of JSONArray, defaultValue otherwise.
*/
public JSONArray optJSONArray(String key, JSONArray defaultValue) throws JSONException {
Object val = this.opt(key);
if (val != null) {
if (JSONArray.class.isAssignableFrom(val.getClass())) {
return(JSONArray)val;
}
}
return defaultValue;
}
/**
* Put a key/value pair into the JSONObject, but only if key/value are both not null, and only if the key is not present already.
* Provided for compatibility to existing models.
* @param key The ket to place in the array
* @param value The value to place in the array
* @return Reference to the current JSONObject.
* @throws JSONException - Thrown if the key already exists or if key or value is null
*/
public JSONObject putOnce(String key, Object value) throws JSONException {
if (key == null) {
throw new JSONException("Key cannot be null");
}
if (value == null) {
throw new JSONException("Value cannot be null");
}
if (this.containsKey(key)) {
throw new JSONException("Key [" + key + "] already exists in the map");
}
this.put(key,value);
return this;
}
/**
* Put a key/value pair into the JSONObject, but only if the key and value are non-null.
* @param key The keey (attribute) name to assign to the value.
* @param value The value to put into the JSONObject.
* @return Reference to the current JSONObject.
* @throws JSONException - if the value is a non-finite number
*/
public JSONObject putOpt(String key, Object value) throws JSONException {
if (key == null) {
throw new JSONException("Key cannot be null");
}
if (value == null) {
throw new JSONException("Value cannot be null");
}
this.put(key,value);
return this;
}
/**
* Method to return the number of keys in this JSONObject.
* This function merely maps to HashMap.size(). Provided for API compatibility.
* @return returns the number of keys in the JSONObject.
*/
public int length() {
return this.size();
}
/**
* Method to append the 'value' object to the element at entry 'key'.
* If JSONObject.has(key) returns false, a new array is created and the value is appended to it.
* If the object as position key is not an array, then a new JSONArray is created
* and both current and new values are appended to it, then the value of the attribute is set to the new
* array. If the current value is already an array, then 'value' is added to it.
*
* @param key The key/attribute name to append to.
* @param value The value to append to it.
*
* @throws JSONException Thrown if the value to append is not JSONAble.
* @return A reference to this object instance.
*/
public JSONObject append(String key, Object value) throws JSONException {
JSONArray array = null;
if (!this.has(key)) {
array = new JSONArray();
}
else {
Object oldVal = this.get(key);
array = new JSONArray();
if (oldVal == null) {
// Add a null if the key was actually there, but just
// had value of null.
array.add(null);
}
else if (JSONArray.class.isAssignableFrom(oldVal.getClass())) {
array = (JSONArray)oldVal;
} else {
array = new JSONArray();
array.add(oldVal);
}
}
array.add(value);
return put(key,array);
}
/**
* Produce a JSONArray containing the values of the members of this JSONObject
* @param names - A JSONArray containing the a list of key strings. This determines the sequence of values in the result.
* @return A JSONArray of the values found for the names provided.
* @throws JSONException - if errors occur during storing the values in a JSONArray
*/
public JSONArray toJSONArray(JSONArray names) throws JSONException {
Iterator itr = names.iterator();
JSONArray array = new JSONArray();
if (itr != null && itr.hasNext()) {
array.put(this.get(itr.next()));
}
return array;
}
/**
* Method to test if a key exists in the JSONObject.
* @param key The key to test.
* @return true if the key is defined in the JSONObject (regardless of value), or false if the key is not in the JSONObject
*/
public boolean has(String key) {
if (key != null) {
return this.containsKey(key);
}
return false;
}
/**
* Method to test if a key is mapped to null.
* This method will also return true if the key has not been put in the JSONObject yet.
* @param key The key to test for null.
* @return true if the key is not in the map or if the value referenced by the key is null.
*/
public boolean isNull(String key) {
if ( (this.opt(key) == null) || (NULL == this.opt(key)) ) {
return true;
}
return false;
}
/**
* Utility function that returns an iterator of all the keys (attributes) of this JSONObject
* @return An iterator of all keys in the object.
*/
public Iterator keys() {
Set set = this.keySet();
if (set != null) {
return set.iterator();
}
return null;
}
/**
* Utility function that returns a JSONArray of all the names of the keys (attributes) of this JSONObject
* @return All the keys in the JSONObject as a JSONArray.
*/
public JSONArray names() {
Iterator itr = this.keys();
if (itr != null) {
JSONArray array = new JSONArray();
while (itr.hasNext()) {
array.add(itr.next());
}
return array;
}
return null;
}
/**
* Utility function that returns a String[] of all the names of the keys (attributes) of this JSONObject
* @return All the keys in the JSONObject as a String[].
*/
public static String[] getNames(JSONObject obj) {
String[] array = null;
if (obj != null) {
if (obj.size() > 0) {
array = new String[obj.size()];
int pos = 0;
Iterator itr = obj.keys();
if (itr != null) {
while (itr.hasNext()) {
array[pos] = (String)itr.next();
pos++;
}
}
}
}
return array;
}
/**
* Utility function that returns an iterator of all the keys (attributes) of this JSONObject sorted in lexicographic manner (String.compareTo).
* @return An iterator of all keys in the object in lexicographic (character code) sorted order.
*/
public Iterator sortedKeys() {
Iterator itr = this.keys();
if (itr != null && itr.hasNext()) {
Vector vect = new Vector();
while (itr.hasNext()) {
vect.add(itr.next());
}
String[] strs = new String[vect.size()];
vect.copyInto(strs);
java.util.Arrays.sort(strs);
vect.clear();
for (int i = 0; i < strs.length; i++) {
vect.add(strs[i]);
}
return vect.iterator();
}
return null;
}
/**
* End of convenience methods.
*/
/**
* Over-ridden toString() method. Returns the same value as write(), which is a compact JSON String.
* If an error occurs in the serialization, the return will be of format: JSON Generation Error: []
* @return A string of JSON text, if possible.
*/
public String toString() {
return toString(false);
}
/**
* Verbose capable toString method.
* If an error occurs in the serialization, the return will be of format: JSON Generation Error: []
* @param verbose Whether or not to tab-indent the output.
* @return A string of JSON text, if possible.
*/
public String toString(boolean verbose) {
String str = null;
try {
str = write(verbose);
} catch (JSONException jex) {
str = "JSON Generation Error: [" + jex.toString() + "]";
}
return str;
}
/**
* Function to return a string of JSON text with specified indention. Returns the same value as write(indentDepth).
* If an error occurs in the serialization, a JSONException is thrown.
* @return A string of JSON text, if possible.
*/
public String toString(int indentDepth) throws JSONException {
return write(indentDepth);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy