Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id D616D200C3F for ; Tue, 7 Mar 2017 20:21:29 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id D37F3160B8B; Tue, 7 Mar 2017 19:21:29 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 809CB160B82 for ; Tue, 7 Mar 2017 20:21:25 +0100 (CET) Received: (qmail 73595 invoked by uid 500); 7 Mar 2017 19:21:24 -0000 Mailing-List: contact commits-help@geode.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@geode.apache.org Delivered-To: mailing list commits@geode.apache.org Received: (qmail 73420 invoked by uid 99); 7 Mar 2017 19:21:24 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 07 Mar 2017 19:21:24 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 27EA6DFF4E; Tue, 7 Mar 2017 19:21:24 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: dschneider@apache.org To: commits@geode.apache.org Date: Tue, 07 Mar 2017 19:21:27 -0000 Message-Id: <2a20bbb581944a30a379a2a7360aa2ab@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [04/51] [abbrv] geode git commit: GEODE-2142: Adding JSON library from the https://github.com/tdunning/open-json project archived-at: Tue, 07 Mar 2017 19:21:30 -0000 GEODE-2142: Adding JSON library from the https://github.com/tdunning/open-json project Project: http://git-wip-us.apache.org/repos/asf/geode/repo Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/b34e47ff Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/b34e47ff Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/b34e47ff Branch: refs/heads/feature/GEM-1195 Commit: b34e47ffaa92007cf059ae5257e481bfb048bfb3 Parents: a2f47b7 Author: Udo Kohlmeyer Authored: Fri Feb 17 14:30:37 2017 -0800 Committer: Udo Kohlmeyer Committed: Mon Feb 27 07:18:55 2017 -0800 ---------------------------------------------------------------------- geode-json/build.gradle | 22 + geode-json/src/main/java/org/json/JSON.java | 116 ++ .../src/main/java/org/json/JSONArray.java | 759 +++++++++++ .../src/main/java/org/json/JSONException.java | 57 + .../src/main/java/org/json/JSONObject.java | 993 +++++++++++++++ .../src/main/java/org/json/JSONString.java | 18 + .../src/main/java/org/json/JSONStringer.java | 470 +++++++ .../src/main/java/org/json/JSONTokener.java | 658 ++++++++++ geode-json/src/test/java/org/json/FileTest.java | 287 +++++ .../src/test/java/org/json/JSONArrayTest.java | 608 +++++++++ .../java/org/json/JSONFunctionTestObject.java | 17 + .../src/test/java/org/json/JSONObjectTest.java | 1198 ++++++++++++++++++ .../test/java/org/json/JSONStringerTest.java | 421 ++++++ .../src/test/java/org/json/JSONTokenerTest.java | 621 +++++++++ .../src/test/java/org/json/ParsingTest.java | 294 +++++ .../src/test/java/org/json/SelfUseTest.java | 276 ++++ geode-json/src/test/resources/sample-01.json | 227 ++++ 17 files changed, 7042 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/geode/blob/b34e47ff/geode-json/build.gradle ---------------------------------------------------------------------- diff --git a/geode-json/build.gradle b/geode-json/build.gradle new file mode 100644 index 0000000..5715685 --- /dev/null +++ b/geode-json/build.gradle @@ -0,0 +1,22 @@ +/* + * 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. + */ + +dependencies { + compile project(':geode-core') + compile project(':geode-common') + testCompile files(project(':geode-core').sourceSets.test.output) +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/geode/blob/b34e47ff/geode-json/src/main/java/org/json/JSON.java ---------------------------------------------------------------------- diff --git a/geode-json/src/main/java/org/json/JSON.java b/geode-json/src/main/java/org/json/JSON.java new file mode 100755 index 0000000..1b32e69 --- /dev/null +++ b/geode-json/src/main/java/org/json/JSON.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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 org.json; + +class JSON { + /** + * Returns the input if it is a JSON-permissible value; throws otherwise. + */ + static double checkDouble(double d) throws JSONException { + if (Double.isInfinite(d) || Double.isNaN(d)) { + throw new JSONException("Forbidden numeric value: " + d); + } + return d; + } + + static Boolean toBoolean(Object value) { + if (value instanceof Boolean) { + return (Boolean) value; + } else if (value instanceof String) { + String stringValue = (String) value; + if ("true".equalsIgnoreCase(stringValue)) { + return true; + } else if ("false".equalsIgnoreCase(stringValue)) { + return false; + } + } + return null; + } + + static Double toDouble(Object value) { + if (value instanceof Double) { + return (Double) value; + } else if (value instanceof Number) { + return ((Number) value).doubleValue(); + } else if (value instanceof String) { + try { + return Double.valueOf((String) value); + } catch (NumberFormatException ignored) { + } + } + return null; + } + + static Integer toInteger(Object value) { + if (value instanceof Integer) { + return (Integer) value; + } else if (value instanceof Number) { + return ((Number) value).intValue(); + } else if (value instanceof String) { + try { + return (int) Double.parseDouble((String) value); + } catch (NumberFormatException ignored) { + } + } + return null; + } + + static Long toLong(Object value) { + if (value instanceof Long) { + return (Long) value; + } else if (value instanceof Number) { + return ((Number) value).longValue(); + } else if (value instanceof String) { + try { + return (long) Double.parseDouble((String) value); + } catch (NumberFormatException ignored) { + } + } + return null; + } + + static String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value != null) { + return String.valueOf(value); + } + return null; + } + + public static JSONException typeMismatch(Object indexOrName, Object actual, + String requiredType) throws JSONException { + if (actual == null) { + throw new JSONException("Value at " + indexOrName + " is null."); + } else { + throw new JSONException("Value " + actual + " at " + indexOrName + + " of type " + actual.getClass().getName() + + " cannot be converted to " + requiredType); + } + } + + public static JSONException typeMismatch(Object actual, String requiredType) + throws JSONException { + if (actual == null) { + throw new JSONException("Value is null."); + } else { + throw new JSONException("Value " + actual + + " of type " + actual.getClass().getName() + + " cannot be converted to " + requiredType); + } + } +} http://git-wip-us.apache.org/repos/asf/geode/blob/b34e47ff/geode-json/src/main/java/org/json/JSONArray.java ---------------------------------------------------------------------- diff --git a/geode-json/src/main/java/org/json/JSONArray.java b/geode-json/src/main/java/org/json/JSONArray.java new file mode 100755 index 0000000..074624d --- /dev/null +++ b/geode-json/src/main/java/org/json/JSONArray.java @@ -0,0 +1,759 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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 org.json; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +// Note: this class was written without inspecting the non-free org.json sourcecode. + +/** + * A dense indexed sequence of values. Values may be any mix of + * {@link JSONObject JSONObjects}, other {@link JSONArray JSONArrays}, Strings, + * Booleans, Integers, Longs, Doubles, {@code null} or {@link JSONObject#NULL}. + * Values may not be {@link Double#isNaN() NaNs}, {@link Double#isInfinite() + * infinities}, or of any type not listed here. + * + * {@code JSONArray} has the same type coercion behavior and + * optional/mandatory accessors as {@link JSONObject}. See that class' + * documentation for details. + * + * Warning: this class represents null in two incompatible + * ways: the standard Java {@code null} reference, and the sentinel value {@link + * JSONObject#NULL}. In particular, {@code get} fails if the requested index + * holds the null reference, but succeeds if it holds {@code JSONObject.NULL}. + * + * Instances of this class are not thread safe. Although this class is + * non-final, it was not designed for inheritance and should not be subclassed. + * In particular, self-use by overridable methods is not specified. See + * Effective Java Item 17, "Design and Document or inheritance or else + * prohibit it" for further information. + */ +public class JSONArray { + + private final List values; + + /** + * Creates a {@code JSONArray} with no values. + */ + public JSONArray() { + values = new ArrayList(); + } + + /** + * Creates a new {@code JSONArray} by copying all values from the given + * collection. + * + * @param copyFrom a collection whose values are of supported types. + * Unsupported values are not permitted and will yield an array in an + * inconsistent state. + */ + /* Accept a raw type for API compatibility */ + public JSONArray(Collection copyFrom) { + this(); + if (copyFrom != null) { + for (Object aCopyFrom : copyFrom) { + put(JSONObject.wrap(aCopyFrom)); + } + } + } + + /** + * Creates a new {@code JSONArray} with values from the next array in the + * tokener. + * + * @param readFrom a tokener whose nextValue() method will yield a + * {@code JSONArray}. + * @throws JSONException if the parse fails or doesn't yield a + * {@code JSONArray}. + */ + public JSONArray(JSONTokener readFrom) throws JSONException { + /* + * Getting the parser to populate this could get tricky. Instead, just + * parse to temporary JSONArray and then steal the data from that. + */ + Object object = readFrom.nextValue(); + if (object instanceof JSONArray) { + values = ((JSONArray) object).values; + } else { + throw JSON.typeMismatch(object, "JSONArray"); + } + } + + /** + * Creates a new {@code JSONArray} with values from the JSON string. + * + * @param json a JSON-encoded string containing an array. + * @throws JSONException if the parse fails or doesn't yield a {@code + * JSONArray}. + */ + public JSONArray(String json) throws JSONException { + this(new JSONTokener(json)); + } + + /** + * Creates a new {@code JSONArray} with values from the given primitive array. + * + * @param array The values to use. + * @throws JSONException if any of the values are non-finite double values (i.e. NaN or infinite) + */ + public JSONArray(Object array) throws JSONException { + if (!array.getClass().isArray()) { + throw new JSONException("Not a primitive array: " + array.getClass()); + } + final int length = Array.getLength(array); + values = new ArrayList(length); + for (int i = 0; i < length; ++i) { + put(JSONObject.wrap(Array.get(array, i))); + } + } + + /** + * @return Returns the number of values in this array. + */ + public int length() { + return values.size(); + } + + /** + * Appends {@code value} to the end of this array. + * + * @param value The value to append. + * @return this array. + */ + public JSONArray put(boolean value) { + values.add(value); + return this; + } + + /** + * Appends {@code value} to the end of this array. + * + * @param value a finite value. May not be {@link Double#isNaN() NaNs} or + * {@link Double#isInfinite() infinities}. + * @return this array. + * @throws JSONException If the value is unacceptable. + */ + public JSONArray put(double value) throws JSONException { + values.add(JSON.checkDouble(value)); + return this; + } + + /** + * Appends {@code value} to the end of this array. + * + * @param value The value to append. + * @return this array. + */ + public JSONArray put(int value) { + values.add(value); + return this; + } + + /** + * Appends {@code value} to the end of this array. + * + * @param value The value to append. + * @return this array. + */ + public JSONArray put(long value) { + values.add(value); + return this; + } + + /** + * Appends {@code value} wrapped by {@link JSONArray} to the end of this array. + * + * @param value any collection. + * @return this array. + */ + public JSONArray put(Collection value) { + if (value == null) { + return put((Object)null); + } + values.add(new JSONArray(value)); + return this; + } + + /** + * Appends {@code value} to the end of this array. + * + * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean, + * Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May + * not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite() + * infinities}. Unsupported values are not permitted and will cause the + * array to be in an inconsistent state. + * @return this array. + */ + public JSONArray put(Object value) { + values.add(value); + return this; + } + + /** + * Same as {@link #put}, with added validity checks. + * + * @param value The value to append. + */ + void checkedPut(Object value) throws JSONException { + if (value instanceof Number) { + JSON.checkDouble(((Number) value).doubleValue()); + } + + put(value); + } + + /** + * Sets the value at {@code index} to {@code value}, null padding this array + * to the required length if necessary. If a value already exists at {@code + * index}, it will be replaced. + * + * @param index Where to put the value. + * @param value The value to set. + * @return this array. + * @throws JSONException This should never happen. + */ + public JSONArray put(int index, boolean value) throws JSONException { + return put(index, (Boolean) value); + } + + /** + * Sets the value at {@code index} to {@code value}, null padding this array + * to the required length if necessary. If a value already exists at {@code + * index}, it will be replaced. + * + * @param index Where to put the value. + * @param value a finite value. May not be {@link Double#isNaN() NaNs} or + * {@link Double#isInfinite() infinities}. + * @return this array. + * @throws JSONException If the value is not a finite value. + */ + public JSONArray put(int index, double value) throws JSONException { + return put(index, (Double) value); + } + + /** + * Sets the value at {@code index} to {@code value}, null padding this array + * to the required length if necessary. If a value already exists at {@code + * index}, it will be replaced. + * + * @param index Where to put the value. + * @param value The value to set. + * @return this array. + * @throws JSONException Should never actually happen. + */ + public JSONArray put(int index, int value) throws JSONException { + return put(index, (Integer) value); + } + + /** + * Sets the value at {@code index} to {@code value}, null padding this array + * to the required length if necessary. If a value already exists at {@code + * index}, it will be replaced. + * + * @param index Where to put the value. + * @param value The value to set. + * @return this array. + * @throws JSONException Should never actually happen. + */ + public JSONArray put(int index, long value) throws JSONException { + return put(index, (Long) value); + } + + /** + * Sets the value at {@code index} to {@code value} wrapped into {@link JSONArray}, + * null padding this array to the required length if necessary. If a value already + * exists at {@code index}, it will be replaced. + * + * @param index Where to put the value. + * @param value The value to set. + * @return this array. + * @throws JSONException Should never actually happen. + */ + public JSONArray put(int index, Collection value) throws JSONException { + if (value == null) { + return put(index, (Object)null); + } + return put(index, new JSONArray(value)); + } + + /** + * Sets the value at {@code index} to {@code value}, null padding this array + * to the required length if necessary. If a value already exists at {@code + * index}, it will be replaced. + * + * @param index Where to put the value. + * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean, + * Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May + * not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite() + * infinities}. + * @return this array. + * @throws JSONException If the value cannot be represented as a finite double value. + */ + public JSONArray put(int index, Object value) throws JSONException { + if (value instanceof Number) { + // deviate from the original by checking all Numbers, not just floats & doubles + JSON.checkDouble(((Number) value).doubleValue()); + } + while (values.size() <= index) { + values.add(null); + } + values.set(index, value); + return this; + } + + /** + * Returns true if this array has no value at {@code index}, or if its value + * is the {@code null} reference or {@link JSONObject#NULL}. + * + * @param index Which value to check. + * @return true if the value is null. + */ + public boolean isNull(int index) { + Object value = opt(index); + return value == null || value == JSONObject.NULL; + } + + /** + * Returns the value at {@code index}. + * + * @param index Which value to get. + * @return the value at the specified location. + * @throws JSONException if this array has no value at {@code index}, or if + * that value is the {@code null} reference. This method returns + * normally if the value is {@code JSONObject#NULL}. + */ + public Object get(int index) throws JSONException { + try { + Object value = values.get(index); + if (value == null) { + throw new JSONException("Value at " + index + " is null."); + } + return value; + } catch (IndexOutOfBoundsException e) { + throw new JSONException("Index " + index + " out of range [0.." + values.size() + ")"); + } + } + + /** + * Returns the value at {@code index}, or null if the array has no value + * at {@code index}. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + public Object opt(int index) { + if (index < 0 || index >= values.size()) { + return null; + } + return values.get(index); + } + + /** + * Removes and returns the value at {@code index}, or null if the array has no value + * at {@code index}. + * + * @param index Which value to remove. + * @return The value previously at the specified location. + */ + public Object remove(int index) { + if (index < 0 || index >= values.size()) { + return null; + } + return values.remove(index); + } + + /** + * Returns the value at {@code index} if it exists and is a boolean or can + * be coerced to a boolean. + * + * @param index Which value to get. + * @return the value at the specified location. + * @throws JSONException if the value at {@code index} doesn't exist or + * cannot be coerced to a boolean. + */ + public boolean getBoolean(int index) throws JSONException { + Object object = get(index); + Boolean result = JSON.toBoolean(object); + if (result == null) { + throw JSON.typeMismatch(index, object, "boolean"); + } + return result; + } + + /** + * Returns the value at {@code index} if it exists and is a boolean or can + * be coerced to a boolean. Returns false otherwise. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + public boolean optBoolean(int index) { + return optBoolean(index, false); + } + + /** + * Returns the value at {@code index} if it exists and is a boolean or can + * be coerced to a boolean. Returns {@code fallback} otherwise. + * + * @param index Which value to get. + * @param fallback the fallback value to return if no value exists. + * @return the value at the specified location or the fallback value. + */ + public boolean optBoolean(int index, boolean fallback) { + Object object = opt(index); + Boolean result = JSON.toBoolean(object); + return result != null ? result : fallback; + } + + /** + * Returns the value at {@code index} if it exists and is a double or can + * be coerced to a double. + * + * @param index Which value to get. + * @return the value at the specified location. + * @throws JSONException if the value at {@code index} doesn't exist or + * cannot be coerced to a double. + */ + public double getDouble(int index) throws JSONException { + Object object = get(index); + Double result = JSON.toDouble(object); + if (result == null) { + throw JSON.typeMismatch(index, object, "double"); + } + return result; + } + + /** + * Returns the value at {@code index} if it exists and is a double or can + * be coerced to a double. Returns {@code NaN} otherwise. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + public double optDouble(int index) { + return optDouble(index, Double.NaN); + } + + /** + * Returns the value at {@code index} if it exists and is a double or can + * be coerced to a double. Returns {@code fallback} otherwise. + * + * @param index Which value to get. + * @param fallback The fallback value to use if no value is at the specified location. + * @return the value at the specified location or the fallback value. + */ + public double optDouble(int index, double fallback) { + Object object = opt(index); + Double result = JSON.toDouble(object); + return result != null ? result : fallback; + } + + /** + * Returns the value at {@code index} if it exists and is an int or + * can be coerced to an int. + * + * @param index Which value to get. + * @return the value at the specified location. + * @throws JSONException if the value at {@code index} doesn't exist or + * cannot be coerced to a int. + */ + public int getInt(int index) throws JSONException { + Object object = get(index); + Integer result = JSON.toInteger(object); + if (result == null) { + throw JSON.typeMismatch(index, object, "int"); + } + return result; + } + + /** + * Returns the value at {@code index} if it exists and is an int or + * can be coerced to an int. Returns 0 otherwise. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + public int optInt(int index) { + return optInt(index, 0); + } + + /** + * Returns the value at {@code index} if it exists and is an int or + * can be coerced to an int. Returns {@code fallback} otherwise. + * + * @param index Which value to get. + * @param fallback The fallback value to use if no value is at the specified location. + * @return the value at the specified location or the fallback value. + */ + public int optInt(int index, int fallback) { + Object object = opt(index); + Integer result = JSON.toInteger(object); + return result != null ? result : fallback; + } + + /** + * Returns the value at {@code index} if it exists and is a long or + * can be coerced to a long. + * + * @param index Which value to get. + * @return the value at the specified location. + * @throws JSONException if the value at {@code index} doesn't exist or + * cannot be coerced to a long. + */ + public long getLong(int index) throws JSONException { + Object object = get(index); + Long result = JSON.toLong(object); + if (result == null) { + throw JSON.typeMismatch(index, object, "long"); + } + return result; + } + + /** + * Returns the value at {@code index} if it exists and is a long or + * can be coerced to a long. Returns 0 otherwise. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + public long optLong(int index) { + return optLong(index, 0L); + } + + /** + * Returns the value at {@code index} if it exists and is a long or + * can be coerced to a long. Returns {@code fallback} otherwise. + * + * @param index Which value to get. + * @param fallback The fallback value to use if no value is at the specified location. + * @return the value at the specified location or the fallback value. + */ + public long optLong(int index, long fallback) { + Object object = opt(index); + Long result = JSON.toLong(object); + return result != null ? result : fallback; + } + + /** + * Returns the value at {@code index} if it exists, coercing it if + * necessary. + * + * @param index Which value to get. + * @return the value at the specified location. + * @throws JSONException if no such value exists. + */ + public String getString(int index) throws JSONException { + Object object = get(index); + String result = JSON.toString(object); + if (result == null) { + throw JSON.typeMismatch(index, object, "String"); + } + return result; + } + + /** + * Returns the value at {@code index} if it exists, coercing it if + * necessary. Returns the empty string if no such value exists. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + public String optString(int index) { + return optString(index, ""); + } + + /** + * Returns the value at {@code index} if it exists, coercing it if + * necessary. Returns {@code fallback} if no such value exists. + * + * @param index Which value to get. + * @param fallback The fallback value to use if no value is at the specified location. + * @return the value at the specified location or the fallback value. + */ + public String optString(int index, String fallback) { + Object object = opt(index); + String result = JSON.toString(object); + return result != null ? result : fallback; + } + + /** + * Returns the value at {@code index} if it exists and is a {@code + * JSONArray}. + * + * @param index Which value to get. + * @return the value at the specified location. + * @throws JSONException if the value doesn't exist or is not a {@code + * JSONArray}. + */ + public JSONArray getJSONArray(int index) throws JSONException { + Object object = get(index); + if (object instanceof JSONArray) { + return (JSONArray) object; + } else { + throw JSON.typeMismatch(index, object, "JSONArray"); + } + } + + /** + * Returns the value at {@code index} if it exists and is a {@code + * JSONArray}. Returns null otherwise. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + public JSONArray optJSONArray(int index) { + Object object = opt(index); + return object instanceof JSONArray ? (JSONArray) object : null; + } + + /** + * Returns the value at {@code index} if it exists and is a {@code + * JSONObject}. + * + * @param index Which value to get. + * @return the value at the specified location. + * @throws JSONException if the value doesn't exist or is not a {@code + * JSONObject}. + */ + public JSONObject getJSONObject(int index) throws JSONException { + Object object = get(index); + if (object instanceof JSONObject) { + return (JSONObject) object; + } else { + throw JSON.typeMismatch(index, object, "JSONObject"); + } + } + + /** + * Returns the value at {@code index} if it exists and is a {@code + * JSONObject}. Returns null otherwise. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + public JSONObject optJSONObject(int index) { + Object object = opt(index); + return object instanceof JSONObject ? (JSONObject) object : null; + } + + /** + * Returns a new object whose values are the values in this array, and whose + * names are the values in {@code names}. Names and values are paired up by + * index from 0 through to the shorter array's length. Names that are not + * strings will be coerced to strings. This method returns null if either + * array is empty. + * + * @param names The names to apply to the returned values. + * @return the newly constructed object. + * @throws JSONException Should not be possible. + */ + public JSONObject toJSONObject(JSONArray names) throws JSONException { + JSONObject result = new JSONObject(); + int length = Math.min(names.length(), values.size()); + if (length == 0) { + return null; + } + for (int i = 0; i < length; i++) { + String name = JSON.toString(names.opt(i)); + result.put(name, opt(i)); + } + return result; + } + + /** + * Returns a new string by alternating this array's values with {@code + * separator}. This array's string values are quoted and have their special + * characters escaped. For example, the array containing the strings '12" + * pizza', 'taco' and 'soda' joined on '+' returns this: + *
"12\" pizza"+"taco"+"soda"
+ * + * @param separator The string used to separate the returned values. + * @return the conjoined values. + * @throws JSONException Only if there is a coding error. + */ + public String join(String separator) throws JSONException { + JSONStringer stringer = new JSONStringer(); + stringer.open(JSONStringer.Scope.NULL, ""); + for (int i = 0, size = values.size(); i < size; i++) { + if (i > 0) { + stringer.out.append(separator); + } + stringer.value(values.get(i)); + } + stringer.close(JSONStringer.Scope.NULL, JSONStringer.Scope.NULL, ""); + return stringer.out.toString(); + } + + /** + * Encodes this array as a compact JSON string, such as: + *
[94043,90210]
+ * + * @return The string form of this array. + */ + @Override + public String toString() { + try { + JSONStringer stringer = new JSONStringer(); + writeTo(stringer); + return stringer.toString(); + } catch (JSONException e) { + return null; + } + } + + /** + * Encodes this array as a human readable JSON string for debugging, such + * as: + *
+     * [
+     *     94043,
+     *     90210
+     * ]
+ * + * @param indentSpaces the number of spaces to indent for each level of + * nesting. + * @return The string form of this array. + * @throws JSONException Only if there is a coding error. + */ + public String toString(int indentSpaces) throws JSONException { + JSONStringer stringer = new JSONStringer(indentSpaces); + writeTo(stringer); + return stringer.toString(); + } + + void writeTo(JSONStringer stringer) throws JSONException { + stringer.array(); + for (Object value : values) { + stringer.value(value); + } + stringer.endArray(); + } + + @Override + public boolean equals(Object o) { + return o instanceof JSONArray && ((JSONArray) o).values.equals(values); + } + + @Override + public int hashCode() { + // diverge from the original, which doesn't implement hashCode + return values.hashCode(); + } +} http://git-wip-us.apache.org/repos/asf/geode/blob/b34e47ff/geode-json/src/main/java/org/json/JSONException.java ---------------------------------------------------------------------- diff --git a/geode-json/src/main/java/org/json/JSONException.java b/geode-json/src/main/java/org/json/JSONException.java new file mode 100755 index 0000000..1292e86 --- /dev/null +++ b/geode-json/src/main/java/org/json/JSONException.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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 org.json; + +// Note: this class was written without inspecting the non-free org.json sourcecode. + +/** + * Thrown to indicate a problem with the JSON API. Such problems include: + *
    + *
  • Attempts to parse or construct malformed documents + *
  • Use of null as a name + *
  • Use of numeric types not available to JSON, such as {@link + * Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}. + *
  • Lookups using an out of range index or nonexistent name + *
  • Type mismatches on lookups + *
+ * + *

Although this is a checked exception, it is rarely recoverable. Most + * callers should simply wrap this exception in an unchecked exception and + * rethrow: + *

  public JSONArray toJSONObject() {
+ *     try {
+ *         JSONObject result = new JSONObject();
+ *         ...
+ *     } catch (JSONException e) {
+ *         throw new RuntimeException(e);
+ *     }
+ * }
+ */ +public class JSONException extends RuntimeException { + + public JSONException(String s) { + super(s); + } + + public JSONException(Throwable cause) { + super(cause); + } + + public JSONException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/geode/blob/b34e47ff/geode-json/src/main/java/org/json/JSONObject.java ---------------------------------------------------------------------- diff --git a/geode-json/src/main/java/org/json/JSONObject.java b/geode-json/src/main/java/org/json/JSONObject.java new file mode 100755 index 0000000..d2bc126 --- /dev/null +++ b/geode-json/src/main/java/org/json/JSONObject.java @@ -0,0 +1,993 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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 org.json; + +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +// Note: this class was written without inspecting the non-free org.json sourcecode. + +/** + * A modifiable set of name/value mappings. Names are unique, non-null strings. + * Values may be any mix of {@link JSONObject JSONObjects}, {@link JSONArray + * JSONArrays}, Strings, Booleans, Integers, Longs, Doubles or {@link #NULL}. + * Values may not be {@code null}, {@link Double#isNaN() NaNs}, {@link + * Double#isInfinite() infinities}, or of any type not listed here. + * + *

This class can coerce values to another type when requested. + *

+ * + *

This class can look up both mandatory and optional values: + *

    + *
  • Use getType() to retrieve a mandatory value. This + * fails with a {@code JSONException} if the requested name has no value + * or if the value cannot be coerced to the requested type. + *
  • Use optType() to retrieve an optional value. This + * returns a system- or user-supplied default if the requested name has no + * value or if the value cannot be coerced to the requested type. + *
+ * + *

Warning: this class represents null in two incompatible + * ways: the standard Java {@code null} reference, and the sentinel value {@link + * JSONObject#NULL}. In particular, calling {@code put(name, null)} removes the + * named entry from the object but {@code put(name, JSONObject.NULL)} stores an + * entry whose value is {@code JSONObject.NULL}. + * + *

Instances of this class are not thread safe. Although this class is + * nonfinal, it was not designed for inheritance and should not be subclassed. + * In particular, self-use by overrideable methods is not specified. See + * Effective Java Item 17, "Design and Document or inheritance or else + * prohibit it" for further information. + */ +public class JSONObject { + + private static final Double NEGATIVE_ZERO = -0d; + + /** + * A sentinel value used to explicitly define a name with no value. Unlike + * {@code null}, names with this value: + *

    + *
  • show up in the {@link #names} array + *
  • show up in the {@link #keys} iterator + *
  • return {@code true} for {@link #has(String)} + *
  • do not throw on {@link #get(String)} + *
  • are included in the encoded JSON string. + *
+ * + *

This value violates the general contract of {@link Object#equals} by + * returning true when compared to {@code null}. Its {@link #toString} + * method returns "null". + */ + public static final Object NULL = new Object() { + @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") + @Override + public boolean equals(Object o) { + return o == this || o == null; // API specifies this broken equals implementation + } + + // at least make the broken equals(null) consistent with Objects.hashCode(null). + @Override + public int hashCode() { + return 0; + } + + @Override + public String toString() { + return "null"; + } + }; + + private final LinkedHashMap nameValuePairs; + + /** + * Creates a {@code JSONObject} with no name/value mappings. + */ + public JSONObject() { + nameValuePairs = new LinkedHashMap(); + } + + /** + * Creates a new {@code JSONObject} by copying all name/value mappings from + * the given map. + * + * @param copyFrom a map whose keys are of type {@link String} and whose + * values are of supported types. + * @throws NullPointerException if any of the map's keys are null. + */ + /* (accept a raw type for API compatibility) */ + public JSONObject(Map copyFrom) { + this(); + Map contentsTyped = (Map) copyFrom; + for (Map.Entry entry : contentsTyped.entrySet()) { + /* + * Deviate from the original by checking that keys are non-null and + * of the proper type. (We still defer validating the values). + */ + String key = (String) entry.getKey(); + if (key == null) { + throw new NullPointerException("key == null"); + } + nameValuePairs.put(key, wrap(entry.getValue())); + } + } + + /** + * Creates a new {@code JSONObject} with name/value mappings from the next + * object in the tokener. + * + * @param readFrom a tokener whose nextValue() method will yield a + * {@code JSONObject}. + * @throws JSONException if the parse fails or doesn't yield a + * {@code JSONObject}. + */ + public JSONObject(JSONTokener readFrom) throws JSONException { + /* + * Getting the parser to populate this could get tricky. Instead, just + * parse to temporary JSONObject and then steal the data from that. + */ + Object object = readFrom.nextValue(); + if (object instanceof JSONObject) { + this.nameValuePairs = ((JSONObject) object).nameValuePairs; + } else { + throw JSON.typeMismatch(object, "JSONObject"); + } + } + + /** + * Creates a new {@code JSONObject} with name/value mappings from the JSON + * string. + * + * @param json a JSON-encoded string containing an object. + * @throws JSONException if the parse fails or doesn't yield a {@code + * JSONObject}. + */ + public JSONObject(String json) throws JSONException { + this(new JSONTokener(json)); + } + + /** + * Creates a new {@code JSONObject} by copying mappings for the listed names + * from the given object. Names that aren't present in {@code copyFrom} will + * be skipped. + * + * @param copyFrom The source object. + * @param names The names of the fields to copy. + * @throws JSONException On internal errors. Shouldn't happen. + */ + public JSONObject(JSONObject copyFrom, String[] names) throws JSONException { + this(); + for (String name : names) { + Object value = copyFrom.opt(name); + if (value != null) { + nameValuePairs.put(name, value); + } + } + } + + /** + * Creates a json object from a bean + * @param bean the bean to create the json object from + * @throws JSONException If there is an exception while reading the bean + */ + public JSONObject(Object bean) throws JSONException { + this(propertiesAsMap(bean)); + } + + private static Map propertiesAsMap(Object bean) throws JSONException { + Map props = new TreeMap(); + try { + PropertyDescriptor[] properties = Introspector.getBeanInfo(bean.getClass(), Object.class) + .getPropertyDescriptors(); + for (PropertyDescriptor prop : properties) { + Object v = prop.getReadMethod().invoke(bean); + props.put(prop.getDisplayName(), wrap(v)); + } + } catch (IllegalAccessException e) { + throw new JSONException(e); + } catch (IntrospectionException e) { + throw new JSONException(e); + } catch (InvocationTargetException e) { + throw new JSONException(e); + } + return props; + } + + public static String[] getNames(JSONObject x) { + Set names = x.keySet(); + String[] r = new String[names.size()]; + int i = 0; + for (String name : names) { + r[i++] = name; + } + return r; + } + + /** + * Returns the number of name/value mappings in this object. + * + * @return the length of this. + */ + public int length() { + return nameValuePairs.size(); + } + + /** + * Maps {@code name} to {@code value}, clobbering any existing name/value + * mapping with the same name. + * + * @param name The name of the value to insert. + * @param value The value to insert. + * @return this object. + * @throws JSONException Should not be possible. + */ + public JSONObject put(String name, boolean value) throws JSONException { + nameValuePairs.put(checkName(name), value); + return this; + } + + /** + * Maps {@code name} to {@code value}, clobbering any existing name/value + * mapping with the same name. + * + * @param name The name for the new value. + * @param value a finite value. May not be {@link Double#isNaN() NaNs} or + * {@link Double#isInfinite() infinities}. + * @return this object. + * @throws JSONException if value is NaN or infinite. + */ + public JSONObject put(String name, double value) throws JSONException { + nameValuePairs.put(checkName(name), JSON.checkDouble(value)); + return this; + } + + /** + * Maps {@code name} to {@code value}, clobbering any existing name/value + * mapping with the same name. + * + * @param name The name for the new value. + * @param value The new value. + * @return this object. + * @throws JSONException Should not be possible. + */ + public JSONObject put(String name, int value) throws JSONException { + nameValuePairs.put(checkName(name), value); + return this; + } + + /** + * Maps {@code name} to {@code value}, clobbering any existing name/value + * mapping with the same name. + * + * @param name The name of the new value. + * @param value The new value to insert. + * @return this object. + * @throws JSONException Should not be possible. + */ + public JSONObject put(String name, long value) throws JSONException { + nameValuePairs.put(checkName(name), value); + return this; + } + + /** + * Maps {@code name} to {@code value}, clobbering any existing name/value + * mapping with the same name. If the value is {@code null}, any existing + * mapping for {@code name} is removed. + * + * @param name The name of the new value. + * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean, + * Integer, Long, Double, {@link #NULL}, or {@code null}. May not be + * {@link Double#isNaN() NaNs} or {@link Double#isInfinite() + * infinities}. + * @return this object. + * @throws JSONException if the value is an invalid double (infinite or NaN). + */ + public JSONObject put(String name, Object value) throws JSONException { + if (value == null) { + nameValuePairs.remove(name); + return this; + } + if (value instanceof Number) { + // deviate from the original by checking all Numbers, not just floats & doubles + JSON.checkDouble(((Number) value).doubleValue()); + } + nameValuePairs.put(checkName(name), value); + return this; + } + + /** + * Equivalent to {@code put(name, value)} when both parameters are non-null; + * does nothing otherwise. + * + * @param name The name of the value to insert. + * @param value The value to insert. + * @return this object. + * @throws JSONException if the value is an invalid double (infinite or NaN). + */ + public JSONObject putOpt(String name, Object value) throws JSONException { + if (name == null || value == null) { + return this; + } + return put(name, value); + } + + /** + * Appends {@code value} to the array already mapped to {@code name}. If + * this object has no mapping for {@code name}, this inserts a new mapping. + * If the mapping exists but its value is not an array, the existing + * and new values are inserted in order into a new array which is itself + * mapped to {@code name}. In aggregate, this allows values to be added to a + * mapping one at a time. + * + * Note that {@code append(String, Object)} provides better semantics. + * In particular, the mapping for {@code name} will always be a + * {@link JSONArray}. Using {@code accumulate} will result in either a + * {@link JSONArray} or a mapping whose type is the type of {@code value} + * depending on the number of calls to it. + * + * @param name The name of the field to change. + * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean, + * Integer, Long, Double, {@link #NULL} or null. May not be {@link + * Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}. + * @return this object after mutation. + * @throws JSONException If the object being added is an invalid number. + */ + // TODO: Change {@code append) to {@link #append} when append is + // unhidden. + public JSONObject accumulate(String name, Object value) throws JSONException { + Object current = nameValuePairs.get(checkName(name)); + if (current == null) { + return put(name, value); + } + + if (current instanceof JSONArray) { + JSONArray array = (JSONArray) current; + array.checkedPut(value); + } else { + JSONArray array = new JSONArray(); + array.checkedPut(current); + array.checkedPut(value); + nameValuePairs.put(name, array); + } + return this; + } + + /** + * Appends values to the array mapped to {@code name}. A new {@link JSONArray} + * mapping for {@code name} will be inserted if no mapping exists. If the existing + * mapping for {@code name} is not a {@link JSONArray}, a {@link JSONException} + * will be thrown. + * + * @param name The name of the array to which the value should be appended. + * @param value The value to append. + * @return this object. + * @throws JSONException if {@code name} is {@code null} or if the mapping for + * {@code name} is non-null and is not a {@link JSONArray}. + */ + public JSONObject append(String name, Object value) throws JSONException { + Object current = nameValuePairs.get(checkName(name)); + + final JSONArray array; + if (current instanceof JSONArray) { + array = (JSONArray) current; + } else if (current == null) { + JSONArray newArray = new JSONArray(); + nameValuePairs.put(name, newArray); + array = newArray; + } else { + throw new JSONException("Key " + name + " is not a JSONArray"); + } + + array.checkedPut(value); + + return this; + } + + String checkName(String name) throws JSONException { + if (name == null) { + throw new JSONException("Names must be non-null"); + } + return name; + } + + /** + * Removes the named mapping if it exists; does nothing otherwise. + * + * @param name The name of the mapping to remove. + * @return the value previously mapped by {@code name}, or null if there was + * no such mapping. + */ + public Object remove(String name) { + return nameValuePairs.remove(name); + } + + /** + * Returns true if this object has no mapping for {@code name} or if it has + * a mapping whose value is {@link #NULL}. + * + * @param name The name of the value to check on. + * @return true if the field doesn't exist or is null. + */ + public boolean isNull(String name) { + Object value = nameValuePairs.get(name); + return value == null || value == NULL; + } + + /** + * Returns true if this object has a mapping for {@code name}. The mapping + * may be {@link #NULL}. + * + * @param name The name of the value to check on. + * @return true if this object has a field named {@code name} + */ + public boolean has(String name) { + return nameValuePairs.containsKey(name); + } + + /** + * Returns the value mapped by {@code name}, or throws if no such mapping exists. + * + * @param name The name of the value to get. + * @return The value. + * @throws JSONException if no such mapping exists. + */ + public Object get(String name) throws JSONException { + Object result = nameValuePairs.get(name); + if (result == null) { + throw new JSONException("No value for " + name); + } + return result; + } + + /** + * Returns the value mapped by {@code name}, or null if no such mapping + * exists. + * + * @param name The name of the value to get. + * @return The value. + */ + public Object opt(String name) { + return nameValuePairs.get(name); + } + + /** + * Returns the value mapped by {@code name} if it exists and is a boolean or + * can be coerced to a boolean, or throws otherwise. + * + * @param name The name of the field we want. + * @return The selected value if it exists. + * @throws JSONException if the mapping doesn't exist or cannot be coerced + * to a boolean. + */ + public boolean getBoolean(String name) throws JSONException { + Object object = get(name); + Boolean result = JSON.toBoolean(object); + if (result == null) { + throw JSON.typeMismatch(name, object, "boolean"); + } + return result; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a boolean or + * can be coerced to a boolean, or false otherwise. + * + * @param name The name of the field we want. + * @return The selected value if it exists. + */ + public boolean optBoolean(String name) { + return optBoolean(name, false); + } + + /** + * Returns the value mapped by {@code name} if it exists and is a boolean or + * can be coerced to a boolean, or {@code fallback} otherwise. + * + * @param name The name of the field we want. + * @param fallback The value to return if the field isn't there. + * @return The selected value or the fallback. + */ + public boolean optBoolean(String name, boolean fallback) { + Object object = opt(name); + Boolean result = JSON.toBoolean(object); + return result != null ? result : fallback; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a double or + * can be coerced to a double, or throws otherwise. + * + * @param name The name of the field we want. + * @return The selected value if it exists. + * @throws JSONException if the mapping doesn't exist or cannot be coerced + * to a double. + */ + public double getDouble(String name) throws JSONException { + Object object = get(name); + Double result = JSON.toDouble(object); + if (result == null) { + throw JSON.typeMismatch(name, object, "double"); + } + return result; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a double or + * can be coerced to a double, or {@code NaN} otherwise. + * + * @param name The name of the field we want. + * @return The selected value if it exists. + */ + public double optDouble(String name) { + return optDouble(name, Double.NaN); + } + + /** + * Returns the value mapped by {@code name} if it exists and is a double or + * can be coerced to a double, or {@code fallback} otherwise. + * + * @param name The name of the field we want. + * @param fallback The value to return if the field isn't there. + * @return The selected value or the fallback. + */ + public double optDouble(String name, double fallback) { + Object object = opt(name); + Double result = JSON.toDouble(object); + return result != null ? result : fallback; + } + + /** + * Returns the value mapped by {@code name} if it exists and is an int or + * can be coerced to an int, or throws otherwise. + * + * @param name The name of the field we want. + * @return The selected value if it exists. + * @throws JSONException if the mapping doesn't exist or cannot be coerced + * to an int. + */ + public int getInt(String name) throws JSONException { + Object object = get(name); + Integer result = JSON.toInteger(object); + if (result == null) { + throw JSON.typeMismatch(name, object, "int"); + } + return result; + } + + /** + * Returns the value mapped by {@code name} if it exists and is an int or + * can be coerced to an int, or 0 otherwise. + * + * @param name The name of the field we want. + * @return The selected value if it exists. + */ + public int optInt(String name) { + return optInt(name, 0); + } + + /** + * Returns the value mapped by {@code name} if it exists and is an int or + * can be coerced to an int, or {@code fallback} otherwise. + * + * @param name The name of the field we want. + * @param fallback The value to return if the field isn't there. + * @return The selected value or the fallback. + */ + public int optInt(String name, int fallback) { + Object object = opt(name); + Integer result = JSON.toInteger(object); + return result != null ? result : fallback; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a long or + * can be coerced to a long, or throws otherwise. + * Note that JSON represents numbers as doubles, + * + * so this is lossy; use strings to transfer numbers + * via JSON without loss. + * + * @param name The name of the field that we want. + * @return The value of the field. + * @throws JSONException if the mapping doesn't exist or cannot be coerced + * to a long. + */ + public long getLong(String name) throws JSONException { + Object object = get(name); + Long result = JSON.toLong(object); + if (result == null) { + throw JSON.typeMismatch(name, object, "long"); + } + return result; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a long or + * can be coerced to a long, or 0 otherwise. Note that JSON represents numbers as doubles, + * so this is lossy; use strings to transfer numbers via JSON. + * + * @param name The name of the field we want. + * @return The selected value. + */ + public long optLong(String name) { + return optLong(name, 0L); + } + + /** + * Returns the value mapped by {@code name} if it exists and is a long or + * can be coerced to a long, or {@code fallback} otherwise. Note that JSON represents + * numbers as doubles, so this is lossy; use strings to transfer + * numbers via JSON. + * + * @param name The name of the field we want. + * @param fallback The value to return if the field isn't there. + * @return The selected value or the fallback. + */ + public long optLong(String name, long fallback) { + Object object = opt(name); + Long result = JSON.toLong(object); + return result != null ? result : fallback; + } + + /** + * Returns the value mapped by {@code name} if it exists, coercing it if + * necessary, or throws if no such mapping exists. + * + * @param name The name of the field we want. + * @return The value of the field. + * @throws JSONException if no such mapping exists. + */ + public String getString(String name) throws JSONException { + Object object = get(name); + String result = JSON.toString(object); + if (result == null) { + throw JSON.typeMismatch(name, object, "String"); + } + return result; + } + + /** + * Returns the value mapped by {@code name} if it exists, coercing it if + * necessary, or the empty string if no such mapping exists. + * + * @param name The name of the field we want. + * @return The value of the field. + */ + public String optString(String name) { + return optString(name, ""); + } + + /** + * Returns the value mapped by {@code name} if it exists, coercing it if + * necessary, or {@code fallback} if no such mapping exists. + * + * @param name The name of the field that we want. + * @param fallback The value to return if the field doesn't exist. + * @return The value of the field or fallback. + */ + public String optString(String name, String fallback) { + Object object = opt(name); + String result = JSON.toString(object); + return result != null ? result : fallback; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a {@code + * JSONArray}, or throws otherwise. + * + * @param name The field we want to get. + * @return The value of the field (if it is a JSONArray. + * @throws JSONException if the mapping doesn't exist or is not a {@code + * JSONArray}. + */ + public JSONArray getJSONArray(String name) throws JSONException { + Object object = get(name); + if (object instanceof JSONArray) { + return (JSONArray) object; + } else { + throw JSON.typeMismatch(name, object, "JSONArray"); + } + } + + /** + * Returns the value mapped by {@code name} if it exists and is a {@code + * JSONArray}, or null otherwise. + * + * @param name The name of the field we want. + * @return The value of the specified field (assuming it is a JSNOArray + */ + public JSONArray optJSONArray(String name) { + Object object = opt(name); + return object instanceof JSONArray ? (JSONArray) object : null; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a {@code + * JSONObject}, or throws otherwise. + * + * @param name The name of the field that we want. + * @return a specified field value (if it is a JSONObject) + * @throws JSONException if the mapping doesn't exist or is not a {@code + * JSONObject}. + */ + public JSONObject getJSONObject(String name) throws JSONException { + Object object = get(name); + if (object instanceof JSONObject) { + return (JSONObject) object; + } else { + throw JSON.typeMismatch(name, object, "JSONObject"); + } + } + + /** + * Returns the value mapped by {@code name} if it exists and is a {@code + * JSONObject}, or null otherwise. + * + * @param name The name of the value we want. + * @return The specified value. + */ + public JSONObject optJSONObject(String name) { + Object object = opt(name); + return object instanceof JSONObject ? (JSONObject) object : null; + } + + /** + * Returns an array with the values corresponding to {@code names}. The + * array contains null for names that aren't mapped. This method returns + * null if {@code names} is either null or empty. + * + * @param names The names of the fields that we want the values for. + * @return The selected values. + * @throws JSONException On internal errors. Shouldn't happen. + */ + public JSONArray toJSONArray(JSONArray names) throws JSONException { + JSONArray result = new JSONArray(); + if (names == null) { + return null; + } + int length = names.length(); + if (length == 0) { + return null; + } + for (int i = 0; i < length; i++) { + String name = JSON.toString(names.opt(i)); + result.put(opt(name)); + } + return result; + } + + /** + * Returns an iterator of the {@code String} names in this object. The + * returned iterator supports {@link Iterator#remove() remove}, which will + * remove the corresponding mapping from this object. If this object is + * modified after the iterator is returned, the iterator's behavior is + * undefined. The order of the keys is undefined. + * + * @return an iterator over the keys. + */ + public Iterator keys() { + return nameValuePairs.keySet().iterator(); + } + + /** + * Returns the set of {@code String} names in this object. The returned set + * is a view of the keys in this object. {@link Set#remove(Object)} will remove + * the corresponding mapping from this object and set iterator behaviour + * is undefined if this object is modified after it is returned. + * + * See {@link #keys()}. + * + * @return The names in this object. + */ + public Set keySet() { + return nameValuePairs.keySet(); + } + + /** + * Returns an array containing the string names in this object. This method + * returns null if this object contains no mappings. + * + * @return the names. + */ + public JSONArray names() { + return nameValuePairs.isEmpty() + ? null + : new JSONArray(new ArrayList(nameValuePairs.keySet())); + } + + /** + * Encodes this object as a compact JSON string, such as: + *

{"query":"Pizza","locations":[94043,90210]}
+ */ + @Override + public String toString() { + try { + JSONStringer stringer = new JSONStringer(); + writeTo(stringer); + return stringer.toString(); + } catch (JSONException e) { + return null; + } + } + + /** + * Encodes this object as a human readable JSON string for debugging, such + * as: + *
+     * {
+     *     "query": "Pizza",
+     *     "locations": [
+     *         94043,
+     *         90210
+     *     ]
+     * }
+ * + * @param indentSpaces the number of spaces to indent for each level of + * nesting. + * @return The string containing the pretty form of this. + * @throws JSONException On internal errors. Shouldn't happen. + */ + public String toString(int indentSpaces) throws JSONException { + JSONStringer stringer = new JSONStringer(indentSpaces); + writeTo(stringer); + return stringer.toString(); + } + + void writeTo(JSONStringer stringer) throws JSONException { + stringer.object(); + for (Map.Entry entry : nameValuePairs.entrySet()) { + stringer.key(entry.getKey()).value(entry.getValue()); + } + stringer.endObject(); + } + + /** + * Encodes the number as a JSON string. + * + * @param number a finite value. May not be {@link Double#isNaN() NaNs} or + * {@link Double#isInfinite() infinities}. + * @return The encoded number in string form. + * @throws JSONException On internal errors. Shouldn't happen. + */ + public static String numberToString(Number number) throws JSONException { + if (number == null) { + throw new JSONException("Number must be non-null"); + } + + double doubleValue = number.doubleValue(); + JSON.checkDouble(doubleValue); + + // the original returns "-0" instead of "-0.0" for negative zero + if (number.equals(NEGATIVE_ZERO)) { + return "-0"; + } + + long longValue = number.longValue(); + if (doubleValue == (double) longValue) { + return Long.toString(longValue); + } + + return number.toString(); + } + + /** + * Encodes {@code data} as a JSON string. This applies quotes and any + * necessary character escaping. + * + * @param data the string to encode. Null will be interpreted as an empty + * string. + * @return the quoted string. + */ + public static String quote(String data) { + if (data == null) { + return "\"\""; + } + try { + JSONStringer stringer = new JSONStringer(); + stringer.open(JSONStringer.Scope.NULL, ""); + stringer.value(data); + stringer.close(JSONStringer.Scope.NULL, JSONStringer.Scope.NULL, ""); + return stringer.toString(); + } catch (JSONException e) { + throw new AssertionError(); + } + } + + /** + * Wraps the given object if necessary. + * + *

If the object is null or , returns {@link #NULL}. + * If the object is a {@code JSONArray} or {@code JSONObject}, no wrapping is necessary. + * If the object is {@code NULL}, no wrapping is necessary. + * If the object is an array or {@code Collection}, returns an equivalent {@code JSONArray}. + * If the object is a {@code Map}, returns an equivalent {@code JSONObject}. + * If the object is a primitive wrapper type or {@code String}, returns the object. + * If the object is from a {@code java} package, returns the result of {@code toString}. + * If the object is some other kind of object then it is assumed to be a bean and is converted to a JSONObject. + * If wrapping fails, returns null. + * + * @param o The object to wrap. + * @return The wrapped (if necessary) form of the object {$code o} + */ + public static Object wrap(Object o) { + if (o == null) { + return NULL; + } + if (o instanceof JSONArray || o instanceof JSONObject) { + return o; + } + if (o.equals(NULL)) { + return o; + } + try { + if (o instanceof Collection) { + return new JSONArray((Collection) o); + } else if (o.getClass().isArray()) { + return new JSONArray(o); + } + if (o instanceof Map) { + return new JSONObject((Map) o); + } + if (o instanceof Boolean || + o instanceof Byte || + o instanceof Character || + o instanceof Double || + o instanceof Float || + o instanceof Integer || + o instanceof Long || + o instanceof Short || + o instanceof String) { + return o; + } + if (o.getClass().getPackage().getName().startsWith("java.") || o instanceof Enum) { + return o.toString(); + } else { + return new JSONObject(o); + } + } catch (Exception ignored) { + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/geode/blob/b34e47ff/geode-json/src/main/java/org/json/JSONString.java ---------------------------------------------------------------------- diff --git a/geode-json/src/main/java/org/json/JSONString.java b/geode-json/src/main/java/org/json/JSONString.java new file mode 100755 index 0000000..34815a8 --- /dev/null +++ b/geode-json/src/main/java/org/json/JSONString.java @@ -0,0 +1,18 @@ +package org.json; +/** + * The JSONString interface allows a toJSONString() + * method so that a class can change the behavior of + * JSONObject.toString(), JSONArray.toString(), + * and JSONWriter.value(Object). The + * toJSONString method will be used instead of the default behavior + * of using the Object's toString() method and quoting the result. + */ +public interface JSONString { + /** + * The toJSONString method allows a class to produce its own JSON + * serialization. + * + * @return A strictly syntactically correct JSON text. + */ + public String toJSONString(); +} \ No newline at end of file