All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ovea.tajin.json.JSONObject Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2011 Ovea 
 *
 * 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 com.ovea.tajin.json;

import java.io.IOException;
import java.io.Writer;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

public class JSONObject extends JSONType implements Iterable {

    private final LinkedHashMap myHashMap = new LinkedHashMap<>();

    public JSONObject() {
    }

    /**
     * Construct a JSONObject from a subset of another JSONObject.
     * An array of strings is used to identify the keys that should be copied.
     * Missing keys are ignored.
     *
     * @param jo A JSONObject.
     * @param sa An array of strings.
     * @throws com.ovea.tajin.json.JSONException If a value is a non-finite number.
     */
    public JSONObject(JSONObject jo, String... sa) throws JSONException {
        for (String aSa : sa) {
            putOpt(aSa, jo.opt(aSa));
        }
    }

    public JSONObject(JSONObject jo) throws JSONException {
        for (String aSa : jo) {
            putOpt(aSa, jo.opt(aSa));
        }
    }

    public JSONObject(JSONObject jo, Iterable sa) throws JSONException {
        for (String aSa : sa) {
            putOpt(aSa, jo.opt(aSa));
        }
    }

    public JSONObject(JSONObject jo, JSONArray sa) throws JSONException {
        for (JSONType aSa : sa) {
            putOpt(aSa.asString(), jo.opt(aSa.asString()));
        }
    }

    /**
     * Construct a JSONObject from a Map.
     *
     * @param map A map object that can be used to initialize the contents of
     *            the JSONObject.
     */
    public JSONObject(Map map) {
        for (Map.Entry entry : map.entrySet()) {
            put(entry.getKey(), entry.getValue());
        }
    }


    /**
     * Construct a JSONObject from an Object, using reflection to find the
     * public members. The resulting JSONObject's keys will be the strings
     * from the names array, and the values will be the field values associated
     * with those keys in the object. If a key is not found or not visible,
     * then it will not be copied into the new JSONObject.
     *
     * @param object An object that has fields that should be used to make a
     *               JSONObject.
     * @param names  An array of strings, the names of the fields to be used
     *               from the object.
     */
    public JSONObject(Object object, Iterable names) {
        Class c = object.getClass();
        for (String name : names) {
            try {
                this.put(name, c.getField(name).get(object));
            } catch (Exception e) {
                try {
                    //noinspection unchecked
                    this.put(name, c.getMethod(name).invoke(object));
                } catch (Exception ee) {
                    try {
                        //noinspection unchecked
                        this.put(name, c.getMethod("get" + Character.toUpperCase(name.charAt(0)) + name.substring(1)).invoke(object));
                    } catch (Exception ignored) {
                    }
                }
            }
        }
    }

    /**
     * Construct a JSONObject from a string.
     * This is the most commonly used JSONObject constructor.
     *
     * @param string A string beginning
     *               with { (left brace) and ending
     *               with } (right brace).
     * @throws com.ovea.tajin.json.JSONException If there is a syntax error in the source string.
     */
    public JSONObject(String string) throws JSONException {
        this(new JSONTokener(string));
    }

    JSONObject(JSONTokener x) throws JSONException {
        this();
        char c;
        String key;

        if (x.nextClean() != '{') {
            throw x.syntaxError("A JSONObject text must begin with '{'");
        }
        for (; ; ) {
            c = x.nextClean();
            switch (c) {
                case 0:
                    throw x.syntaxError("A JSONObject text must end with '}'");
                case '}':
                    return;
                default:
                    x.back();
                    key = x.nextValue().toString();
            }

            /*
             * The key is followed by ':'. We will also tolerate '=' or '=>'.
             */

            c = x.nextClean();
            if (c == '=') {
                if (x.next() != '>') {
                    x.back();
                }
            } else if (c != ':') {
                throw x.syntaxError("Expected a ':' after a key");
            }
            put(key, x.nextValue());

            /*
             * Pairs are separated by ','. We will also tolerate ';'.
             */

            switch (x.nextClean()) {
                case ';':
                case ',':
                    if (x.nextClean() == '}') {
                        return;
                    }
                    x.back();
                    break;
                case '}':
                    return;
                default:
                    throw x.syntaxError("Expected a ',' or '}'");
            }
        }
    }

    /**
     * Accumulate values under a key. It is similar to the put method except
     * that if there is already an object stored under the key then a
     * JSONArray is stored under the key to hold all of the accumulated values.
     * If there is already a JSONArray, then the new value is appended to it.
     * In contrast, the put method replaces the previous value.
     *
     * @param key   A key string.
     * @param value An object to be accumulated under the key.
     * @return this.
     * @throws com.ovea.tajin.json.JSONException If the value is an invalid number
     *                                     or if the key is null.
     */
    public JSONObject accumulate(String key, Object value) throws JSONException {
        JSONType o = opt(key);
        if (o == null) {
            put(key, value);
        } else if (o instanceof JSONArray) {
            ((JSONArray) o).put(value);
        } else {
            put(key, new JSONArray().put(o).put(value));
        }
        return this;
    }


    /**
     * Append values to the array under a key. If the key does not exist in the
     * JSONObject, then the key is put in the JSONObject with its value being a
     * JSONArray containing the value parameter. If the key was already
     * associated with a JSONArray, then the value parameter is appended to it.
     *
     * @param key   A key string.
     * @param value An object to be accumulated under the key.
     * @return this.
     * @throws com.ovea.tajin.json.JSONException If the key is null or if the current value
     *                                     associated with the key is not a JSONArray.
     */
    public JSONObject append(String key, Object value) throws JSONException {
        JSONType o = opt(key);
        if (o == null) {
            put(key, new JSONArray().put(value));
        } else if (!(o instanceof JSONArray)) {
            throw new JSONException("JSONObject[" + key + "] is not a JSONArray.");
        } else {
            ((JSONArray) o).put(value);
        }
        return this;
    }

    /**
     * Get the value object associated with a key.
     *
     * @param key A key string.
     * @return The object associated with the key.
     * @throws com.ovea.tajin.json.JSONException if the key is not found.
     */
    public JSONType get(String key) throws JSONException {
        JSONType o = opt(key);
        if (o == null) {
            throw new JSONException("JSONObject[" + Utils.quote(key) + "] not found.");
        }
        return o;
    }

    /**
     * Get the boolean value associated with a key.
     *
     * @param key A key string.
     * @return The truth.
     * @throws com.ovea.tajin.json.JSONException if the value is not a Boolean or the String "true" or "false".
     */
    public boolean getBoolean(String key) throws JSONException {
        try {
            return get(key).asBoolean();
        } catch (ConversionException e) {
            throw new JSONException("JSONObject[" + Utils.quote(key) + "] is not a boolean.");
        }
    }

    /**
     * Get the double value associated with a key.
     *
     * @param key A key string.
     * @return The numeric value.
     * @throws com.ovea.tajin.json.JSONException if the key is not found or
     *                                     if the value is not a Number object and cannot be converted to a number.
     */
    public double getDouble(String key) throws JSONException {
        try {
            return get(key).asDouble();
        } catch (ConversionException e) {
            throw new JSONException("JSONObject[" + Utils.quote(key) + "] is not a number.");
        }
    }

    /**
     * Get the int value associated with a key. If the number value is too
     * large for an int, it will be clipped.
     *
     * @param key A key string.
     * @return The integer value.
     * @throws com.ovea.tajin.json.JSONException if the key is not found or if the value cannot
     *                                     be converted to an integer.
     */
    public int getInt(String key) throws JSONException {
        try {
            return get(key).asInt();
        } catch (ConversionException e) {
            throw new JSONException("JSONObject[" + Utils.quote(key) + "] is not a number.");
        }
    }

    public JSONArray getArray(String key) throws JSONException {
        JSONType o = get(key);
        if (o.isArray()) {
            return o.asArray();
        }
        throw new JSONException("JSONObject[" + Utils.quote(key) + "] is not a JSONArray.");
    }

    public JSONObject getObject(String key) throws JSONException {
        JSONType o = get(key);
        if (o.isObject()) {
            return o.asObject();
        }
        throw new JSONException("JSONObject[" + Utils.quote(key) + "] is not a JSONObject.");
    }

    public long getLong(String key) throws JSONException {
        try {
            return get(key).asLong();
        } catch (ConversionException e) {
            throw new JSONException("JSONObject[" + Utils.quote(key) + "] is not a number.");
        }
    }

    public String getString(String key) throws JSONException {
        return get(key).asString();
    }

    public boolean has(String key) {
        return this.myHashMap.containsKey(key);
    }

    public boolean isNull(String key) {
        return JSON.NULL.equals(opt(key));
    }

    @Override
    public Iterator iterator() {
        return keys().iterator();
    }

    public Iterable keys() {
        return this.myHashMap.keySet();
    }

    /**
     * Produce a JSONArray containing the names of the elements of this
     * JSONObject.
     *
     * @return A JSONArray containing the key strings, or empty array if the JSONObject
     *         is empty.
     */
    public JSONArray keysArray() {
        return new JSONArray(keys());
    }

    public Iterable> entries() {
        return this.myHashMap.entrySet();
    }

    public int size() {
        return this.myHashMap.size();
    }

    public int length() {
        return size();
    }

    public boolean isEmpty() {
        return this.myHashMap.isEmpty();
    }

    public JSONArray values() {
        return new JSONArray(this.myHashMap.values());
    }

    /**
     * Produce a JSONArray containing the values of the members of this
     * JSONObject.
     *
     * @param names A JSONArray containing a list of key strings. This
     *              determines the sequence of the values in the result.
     * @return A JSONArray of values.
     * @throws com.ovea.tajin.json.JSONException If any of the values are non-finite numbers.
     */
    public JSONArray values(JSONArray names) throws JSONException {
        JSONArray ja = new JSONArray();
        if (names == null || names.length() == 0) {
            return ja;
        }
        for (JSONType name : names) {
            ja.put(this.opt(name.toString()));
        }
        return ja;
    }

    public JSONArray values(String... keys) throws JSONException {
        return values(new JSONArray(Arrays.asList(keys)));
    }

    public JSONArray values(Iterable keys) throws JSONException {
        return values(new JSONArray(keys));
    }

    /**
     * Get an optional value associated with a key.
     *
     * @param key A key string.
     * @return An object which is the value, or null if there is no value.
     */
    public JSONType opt(String key) {
        return key == null ? null : this.myHashMap.get(key);
    }

    /**
     * Get an optional boolean associated with a key.
     * It returns false if there is no such key, or if the value is not
     * Boolean.TRUE or the String "true".
     *
     * @param key A key string.
     * @return The truth.
     */
    public boolean optBoolean(String key) {
        return optBoolean(key, false);
    }

    /**
     * Get an optional boolean associated with a key.
     * It returns the defaultValue if there is no such key, or if it is not
     * a Boolean or the String "true" or "false" (case insensitive).
     *
     * @param key          A key string.
     * @param defaultValue The default.
     * @return The truth.
     */
    public boolean optBoolean(String key, boolean defaultValue) {
        try {
            return getBoolean(key);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * Get an optional double associated with a key,
     * or NaN if there is no such key or if its value is not a number.
     * If the value is a string, an attempt will be made to evaluate it as
     * a number.
     *
     * @param key A string which is the key.
     * @return An object which is the value.
     */
    public double optDouble(String key) {
        return optDouble(key, Double.NaN);
    }


    /**
     * Get an optional double associated with a key, or the
     * defaultValue if there is no such key or if its value is not a number.
     * If the value is a string, an attempt will be made to evaluate it as
     * a number.
     *
     * @param key          A key string.
     * @param defaultValue The default.
     * @return An object which is the value.
     */
    public double optDouble(String key, double defaultValue) {
        try {
            return opt(key).asDouble();
        } catch (Exception e) {
            return defaultValue;
        }
    }


    /**
     * Get an optional int value associated with a key,
     * or zero if there is no such key or if the value is not a number.
     * If the value is a string, an attempt will be made to evaluate it as
     * a number.
     *
     * @param key A key string.
     * @return An object which is the value.
     */
    public int optInt(String key) {
        return optInt(key, 0);
    }


    /**
     * Get an optional int value associated with a key,
     * or the default if there is no such key or if the value is not a number.
     * If the value is a string, an attempt will be made to evaluate it as
     * a number.
     *
     * @param key          A key string.
     * @param defaultValue The default.
     * @return An object which is the value.
     */
    public int optInt(String key, int defaultValue) {
        try {
            return getInt(key);
        } catch (Exception e) {
            return defaultValue;
        }
    }


    /**
     * Get an optional JSONArray associated with a key.
     * It returns null if there is no such key, or if its value is not a
     * JSONArray.
     *
     * @param key A key string.
     * @return A JSONArray which is the value.
     */
    public JSONArray optArray(String key) {
        JSONType o = opt(key);
        return o instanceof JSONArray ? (JSONArray) o : null;
    }

    /**
     * Get an optional JSONObject associated with a key.
     * It returns null if there is no such key, or if its value is not a
     * JSONObject.
     *
     * @param key A key string.
     * @return A JSONObject which is the value.
     */
    public JSONObject optObject(String key) {
        JSONType o = opt(key);
        return o instanceof JSONObject ? (JSONObject) o : null;
    }

    /**
     * Get an optional long value associated with a key,
     * or zero if there is no such key or if the value is not a number.
     * If the value is a string, an attempt will be made to evaluate it as
     * a number.
     *
     * @param key A key string.
     * @return An object which is the value.
     */
    public long optLong(String key) {
        return optLong(key, 0);
    }


    /**
     * Get an optional long value associated with a key,
     * or the default if there is no such key or if the value is not a number.
     * If the value is a string, an attempt will be made to evaluate it as
     * a number.
     *
     * @param key          A key string.
     * @param defaultValue The default.
     * @return An object which is the value.
     */
    public long optLong(String key, long defaultValue) {
        try {
            return getLong(key);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * Get an optional string associated with a key.
     * It returns an empty string if there is no such key. If the value is not
     * a string and is not null, then it is coverted to a string.
     *
     * @param key A key string.
     * @return A string which is the value.
     */
    public String optString(String key) {
        return optString(key, "");
    }


    /**
     * Get an optional string associated with a key.
     * It returns the defaultValue if there is no such key.
     *
     * @param key          A key string.
     * @param defaultValue The default.
     * @return A string which is the value.
     */
    public String optString(String key, String defaultValue) {
        JSONType o = opt(key);
        return o != null ? o.asString() : defaultValue;
    }

    /**
     * Put a key/value pair in the JSONObject, where the value will be a
     * JSONArray which is produced from a Collection.
     *
     * @param key   A key string.
     * @param value A Collection value.
     * @return this.
     * @throws com.ovea.tajin.json.JSONException
     */
    public JSONObject put(String key, Iterable value) throws JSONException {
        put(key, JSON.valueOf(value));
        return this;
    }

    public JSONObject putNull(String key) throws JSONException {
        return put(key, JSON.NULL);
    }

    public JSONObject put(String key, Object... values) throws JSONException {
        put(key, JSON.valueOf(values));
        return this;
    }

    /**
     * Put a key/boolean pair in the JSONObject.
     *
     * @param key   A key string.
     * @param value A boolean which is the value.
     * @return this.
     * @throws com.ovea.tajin.json.JSONException If the key is null.
     */
    public JSONObject put(String key, boolean value) throws JSONException {
        put(key, value ? Boolean.TRUE : Boolean.FALSE);
        return this;
    }


    /**
     * Put a key/double pair in the JSONObject.
     *
     * @param key   A key string.
     * @param value A double which is the value.
     * @return this.
     * @throws com.ovea.tajin.json.JSONException If the key is null or if the number is invalid.
     */
    public JSONObject put(String key, double value) throws JSONException {
        put(key, new Double(value));
        return this;
    }


    /**
     * Put a key/int pair in the JSONObject.
     *
     * @param key   A key string.
     * @param value An int which is the value.
     * @return this.
     * @throws com.ovea.tajin.json.JSONException If the key is null.
     */
    public JSONObject put(String key, int value) throws JSONException {
        put(key, new Integer(value));
        return this;
    }


    /**
     * Put a key/long pair in the JSONObject.
     *
     * @param key   A key string.
     * @param value A long which is the value.
     * @return this.
     * @throws com.ovea.tajin.json.JSONException If the key is null.
     */
    public JSONObject put(String key, long value) throws JSONException {
        put(key, new Long(value));
        return this;
    }


    /**
     * Put a key/value pair in the JSONObject, where the value will be a
     * JSONObject which is produced from a Map.
     *
     * @param key   A key string.
     * @param value A Map value.
     * @return this.
     * @throws com.ovea.tajin.json.JSONException
     */
    public JSONObject put(String key, Map value) throws JSONException {
        put(key, new JSONObject(value));
        return this;
    }


    /**
     * Put a key/value pair in the JSONObject. If the value is null,
     * then the key will be removed from the JSONObject if it is present.
     *
     * @param key   A key string.
     * @param value An object which is the value. It should be of one of these
     *              types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String,
     *              or the JSON.NULL object.
     * @return this.
     * @throws com.ovea.tajin.json.JSONException If the value is non-finite number
     *                                     or if the key is null.
     */
    public JSONObject put(String key, Object value) throws JSONException {
        this.myHashMap.put(key, JSON.valueOf(value));
        return this;
    }


    /**
     * Put a key/value pair in the JSONObject, but only if the
     * key and the value are both non-null.
     *
     * @param key   A key string.
     * @param value An object which is the value. It should be of one of these
     *              types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String,
     *              or the JSON.NULL object.
     * @return this.
     * @throws com.ovea.tajin.json.JSONException If the value is a non-finite number.
     */
    public JSONObject putOpt(String key, Object value) throws JSONException {
        if (key != null && value != null) {
            put(key, value);
        }
        return this;
    }

    /**
     * Remove a name and its value, if present.
     *
     * @param key The name to be removed.
     * @return The value that was associated with the name,
     *         or null if there was no value.
     */
    public JSONType remove(String key) {
        return this.myHashMap.remove(key);
    }

    public JSONObject removeAll(String... keys) {
        for (String key : keys) {
            remove(key);
        }
        return this;
    }

    public JSONObject merge(JSONObject overrides) {
        myHashMap.putAll(overrides.myHashMap);
        return this;
    }

    /**
     * Make a JSON text of this JSONObject. For compactness, no whitespace
     * is added. If this would not result in a syntactically correct JSON text,
     * then '' will be returned instead.
     * 

* Warning: This method assumes that the data structure is acyclical. * * @return a printable, displayable, portable, transmittable * representation of the object, beginning * with { (left brace) and ending * with } (right brace). */ @Override public String toString() { try { StringBuilder sb = new StringBuilder("{"); for (String key : keys()) { if (sb.length() > 1) { sb.append(','); } sb.append(Utils.quote(key)); sb.append(':'); sb.append(this.myHashMap.get(key)); } sb.append('}'); return sb.toString(); } catch (Exception e) { return ""; } } /** * Make a prettyprinted JSON text of this JSONObject. *

* Warning: This method assumes that the data structure is acyclical. * * @param indentFactor The number of spaces to add to each level of * indentation. * @param indent The indentation of the top level. * @return a printable, displayable, transmittable * representation of the object, beginning * with { (left brace) and ending * with } (right brace). * @throws com.ovea.tajin.json.JSONException If the object contains an invalid number. */ @Override public String toString(int indentFactor, int indent) throws JSONException { int i; int n = size(); if (n == 0) { return "{}"; } Iterator keys = keys().iterator(); StringBuilder sb = new StringBuilder("{"); int newindent = indent + indentFactor; String o; if (n == 1) { o = keys.next(); sb.append(Utils.quote(o)); sb.append(": "); sb.append(this.myHashMap.get(o).toString(indentFactor, indent)); } else { while (keys.hasNext()) { o = keys.next(); if (sb.length() > 1) { sb.append(",\n"); } else { sb.append('\n'); } for (i = 0; i < newindent; i += 1) { sb.append(' '); } sb.append(Utils.quote(o)); sb.append(": "); sb.append(this.myHashMap.get(o).toString(indentFactor, newindent)); } if (sb.length() > 1) { sb.append('\n'); for (i = 0; i < indent; i += 1) { sb.append(' '); } } } sb.append('}'); return sb.toString(); } /** * Write the contents of the JSONObject as JSON text to a writer. * For compactness, no whitespace is added. *

* Warning: This method assumes that the data structure is acyclical. * * @return The writer. * @throws com.ovea.tajin.json.JSONException */ @Override public Writer write(Writer writer) throws JSONException { try { boolean b = false; Iterator keys = keys().iterator(); writer.write('{'); while (keys.hasNext()) { if (b) { writer.write(','); } String k = keys.next(); writer.write(Utils.quote(k)); writer.write(':'); JSONType v = this.myHashMap.get(k); if (v instanceof JSONObject || v instanceof JSONArray) { v.write(writer); } else { writer.write(v.toString()); } b = true; } writer.write('}'); return writer; } catch (IOException e) { throw new JSONException(e); } } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; JSONObject object = (JSONObject) o; return myHashMap.equals(object.myHashMap); } @Override public int hashCode() { return myHashMap.hashCode(); } public Map toMap() { return new LinkedHashMap<>(myHashMap); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy