2008-09-01 05:13:32 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2008 Google Inc.
|
|
|
|
*
|
|
|
|
* 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.google.gson;
|
|
|
|
|
2019-03-10 21:33:25 +01:00
|
|
|
import com.google.gson.internal.$Gson$Preconditions;
|
2022-08-04 19:32:30 +02:00
|
|
|
import com.google.gson.internal.LazilyParsedNumber;
|
2008-09-01 05:13:32 +02:00
|
|
|
import java.math.BigDecimal;
|
|
|
|
import java.math.BigInteger;
|
|
|
|
|
|
|
|
/**
|
2022-08-21 22:29:40 +02:00
|
|
|
* A class representing a JSON primitive value. A primitive value
|
2008-09-01 05:13:32 +02:00
|
|
|
* is either a String, a Java primitive, or a Java primitive
|
|
|
|
* wrapper type.
|
|
|
|
*
|
|
|
|
* @author Inderjeet Singh
|
2009-04-01 19:03:31 +02:00
|
|
|
* @author Joel Leitch
|
2008-09-01 05:13:32 +02:00
|
|
|
*/
|
|
|
|
public final class JsonPrimitive extends JsonElement {
|
2011-04-28 23:57:29 +02:00
|
|
|
|
2019-03-10 21:33:25 +01:00
|
|
|
private final Object value;
|
2008-09-01 05:13:32 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a primitive containing a boolean value.
|
|
|
|
*
|
|
|
|
* @param bool the value to create the primitive with.
|
|
|
|
*/
|
2022-08-04 19:32:30 +02:00
|
|
|
@SuppressWarnings("deprecation") // superclass constructor
|
2008-09-01 05:13:32 +02:00
|
|
|
public JsonPrimitive(Boolean bool) {
|
2019-03-10 21:33:25 +01:00
|
|
|
value = $Gson$Preconditions.checkNotNull(bool);
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a primitive containing a {@link Number}.
|
|
|
|
*
|
|
|
|
* @param number the value to create the primitive with.
|
|
|
|
*/
|
2022-08-04 19:32:30 +02:00
|
|
|
@SuppressWarnings("deprecation") // superclass constructor
|
2008-09-01 05:13:32 +02:00
|
|
|
public JsonPrimitive(Number number) {
|
2019-03-10 21:33:25 +01:00
|
|
|
value = $Gson$Preconditions.checkNotNull(number);
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a primitive containing a String value.
|
|
|
|
*
|
|
|
|
* @param string the value to create the primitive with.
|
|
|
|
*/
|
2022-08-04 19:32:30 +02:00
|
|
|
@SuppressWarnings("deprecation") // superclass constructor
|
2008-09-01 05:13:32 +02:00
|
|
|
public JsonPrimitive(String string) {
|
2019-03-10 21:33:25 +01:00
|
|
|
value = $Gson$Preconditions.checkNotNull(string);
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a primitive containing a character. The character is turned into a one character String
|
2022-08-21 22:29:40 +02:00
|
|
|
* since JSON only supports String.
|
2008-09-01 05:13:32 +02:00
|
|
|
*
|
|
|
|
* @param c the value to create the primitive with.
|
|
|
|
*/
|
2022-08-04 19:32:30 +02:00
|
|
|
@SuppressWarnings("deprecation") // superclass constructor
|
2008-09-01 05:13:32 +02:00
|
|
|
public JsonPrimitive(Character c) {
|
2019-03-10 21:33:25 +01:00
|
|
|
// convert characters to strings since in JSON, characters are represented as a single
|
|
|
|
// character string
|
|
|
|
value = $Gson$Preconditions.checkNotNull(c).toString();
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
|
|
|
|
2017-05-31 19:33:37 +02:00
|
|
|
/**
|
|
|
|
* Returns the same value as primitives are immutable.
|
|
|
|
* @since 2.8.2
|
|
|
|
*/
|
2012-09-03 10:34:37 +02:00
|
|
|
@Override
|
2017-05-31 19:33:37 +02:00
|
|
|
public JsonPrimitive deepCopy() {
|
2012-08-21 03:19:43 +02:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2008-09-01 05:13:32 +02:00
|
|
|
/**
|
|
|
|
* Check whether this primitive contains a boolean value.
|
|
|
|
*
|
|
|
|
* @return true if this primitive contains a boolean value, false otherwise.
|
|
|
|
*/
|
|
|
|
public boolean isBoolean() {
|
|
|
|
return value instanceof Boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-08-21 22:29:40 +02:00
|
|
|
* Convenience method to get this element as a boolean value.
|
|
|
|
* If this primitive {@linkplain #isBoolean() is not a boolean}, the string value
|
|
|
|
* is parsed using {@link Boolean#parseBoolean(String)}. This means {@code "true"} (ignoring
|
|
|
|
* case) is considered {@code true} and any other value is considered {@code false}.
|
2008-09-01 05:13:32 +02:00
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public boolean getAsBoolean() {
|
2011-04-14 04:42:47 +02:00
|
|
|
if (isBoolean()) {
|
2019-03-31 21:28:12 +02:00
|
|
|
return ((Boolean) value).booleanValue();
|
2011-04-14 04:42:47 +02:00
|
|
|
}
|
2019-04-05 16:20:06 +02:00
|
|
|
// Check to see if the value as a String is "true" in any case.
|
|
|
|
return Boolean.parseBoolean(getAsString());
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check whether this primitive contains a Number.
|
|
|
|
*
|
|
|
|
* @return true if this primitive contains a Number, false otherwise.
|
|
|
|
*/
|
|
|
|
public boolean isNumber() {
|
|
|
|
return value instanceof Number;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-08-21 22:29:40 +02:00
|
|
|
* Convenience method to get this element as a {@link Number}.
|
|
|
|
* If this primitive {@linkplain #isString() is a string}, a lazily parsed {@code Number}
|
|
|
|
* is constructed which parses the string when any of its methods are called (which can
|
|
|
|
* lead to a {@link NumberFormatException}).
|
2008-09-01 05:13:32 +02:00
|
|
|
*
|
2022-08-21 22:29:40 +02:00
|
|
|
* @throws UnsupportedOperationException if this primitive is neither a number nor a string.
|
2008-09-01 05:13:32 +02:00
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public Number getAsNumber() {
|
2022-08-21 22:29:40 +02:00
|
|
|
if (value instanceof Number) {
|
|
|
|
return (Number) value;
|
|
|
|
} else if (value instanceof String) {
|
|
|
|
return new LazilyParsedNumber((String) value);
|
|
|
|
}
|
|
|
|
throw new UnsupportedOperationException("Primitive is neither a number nor a string");
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check whether this primitive contains a String value.
|
|
|
|
*
|
|
|
|
* @return true if this primitive contains a String value, false otherwise.
|
|
|
|
*/
|
|
|
|
public boolean isString() {
|
|
|
|
return value instanceof String;
|
|
|
|
}
|
|
|
|
|
2022-08-21 22:29:40 +02:00
|
|
|
// Don't add Javadoc, inherit it from super implementation; no exceptions are thrown here
|
2008-09-01 05:13:32 +02:00
|
|
|
@Override
|
|
|
|
public String getAsString() {
|
2022-08-21 22:29:40 +02:00
|
|
|
if (value instanceof String) {
|
|
|
|
return (String) value;
|
|
|
|
} else if (isNumber()) {
|
2008-12-14 05:42:16 +01:00
|
|
|
return getAsNumber().toString();
|
|
|
|
} else if (isBoolean()) {
|
2019-03-31 21:28:12 +02:00
|
|
|
return ((Boolean) value).toString();
|
2008-12-14 05:42:16 +01:00
|
|
|
}
|
2022-08-21 22:29:40 +02:00
|
|
|
throw new AssertionError("Unexpected value type: " + value.getClass());
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-08-21 22:29:40 +02:00
|
|
|
* @throws NumberFormatException {@inheritDoc}
|
2008-09-01 05:13:32 +02:00
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public double getAsDouble() {
|
2010-09-28 15:42:43 +02:00
|
|
|
return isNumber() ? getAsNumber().doubleValue() : Double.parseDouble(getAsString());
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-08-21 22:29:40 +02:00
|
|
|
* @throws NumberFormatException {@inheritDoc}
|
2008-09-01 05:13:32 +02:00
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public BigDecimal getAsBigDecimal() {
|
2022-08-21 22:29:40 +02:00
|
|
|
return value instanceof BigDecimal ? (BigDecimal) value : new BigDecimal(getAsString());
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-08-21 22:29:40 +02:00
|
|
|
* @throws NumberFormatException {@inheritDoc}
|
2008-09-01 05:13:32 +02:00
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public BigInteger getAsBigInteger() {
|
2011-05-05 01:26:22 +02:00
|
|
|
return value instanceof BigInteger ?
|
2022-08-21 22:29:40 +02:00
|
|
|
(BigInteger) value : new BigInteger(getAsString());
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-08-21 22:29:40 +02:00
|
|
|
* @throws NumberFormatException {@inheritDoc}
|
2008-09-01 05:13:32 +02:00
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public float getAsFloat() {
|
2010-09-28 15:42:43 +02:00
|
|
|
return isNumber() ? getAsNumber().floatValue() : Float.parseFloat(getAsString());
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-08-21 22:29:40 +02:00
|
|
|
* Convenience method to get this element as a primitive long.
|
2008-09-01 05:13:32 +02:00
|
|
|
*
|
2022-08-21 22:29:40 +02:00
|
|
|
* @return this element as a primitive long.
|
|
|
|
* @throws NumberFormatException {@inheritDoc}
|
2008-09-01 05:13:32 +02:00
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public long getAsLong() {
|
2010-09-28 15:42:43 +02:00
|
|
|
return isNumber() ? getAsNumber().longValue() : Long.parseLong(getAsString());
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-08-21 22:29:40 +02:00
|
|
|
* @throws NumberFormatException {@inheritDoc}
|
2008-09-01 05:13:32 +02:00
|
|
|
*/
|
2008-11-20 20:40:12 +01:00
|
|
|
@Override
|
2008-09-01 05:13:32 +02:00
|
|
|
public short getAsShort() {
|
2010-09-28 15:42:43 +02:00
|
|
|
return isNumber() ? getAsNumber().shortValue() : Short.parseShort(getAsString());
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-08-21 22:29:40 +02:00
|
|
|
* @throws NumberFormatException {@inheritDoc}
|
2008-09-01 05:13:32 +02:00
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public int getAsInt() {
|
2010-09-28 15:42:43 +02:00
|
|
|
return isNumber() ? getAsNumber().intValue() : Integer.parseInt(getAsString());
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|
2009-10-09 00:03:08 +02:00
|
|
|
|
2022-08-21 22:29:40 +02:00
|
|
|
/**
|
|
|
|
* @throws NumberFormatException {@inheritDoc}
|
|
|
|
*/
|
2008-11-15 03:26:57 +01:00
|
|
|
@Override
|
|
|
|
public byte getAsByte() {
|
2010-09-28 15:42:43 +02:00
|
|
|
return isNumber() ? getAsNumber().byteValue() : Byte.parseByte(getAsString());
|
2008-11-15 03:26:57 +01:00
|
|
|
}
|
2009-10-09 00:03:08 +02:00
|
|
|
|
2022-08-21 22:29:40 +02:00
|
|
|
/**
|
|
|
|
* @throws UnsupportedOperationException if the string value of this
|
|
|
|
* primitive is empty.
|
|
|
|
* @deprecated This method is misleading, as it does not get this element as a char but rather as
|
|
|
|
* a string's first character.
|
|
|
|
*/
|
|
|
|
@Deprecated
|
2008-11-15 03:26:57 +01:00
|
|
|
@Override
|
|
|
|
public char getAsCharacter() {
|
2022-08-21 22:29:40 +02:00
|
|
|
String s = getAsString();
|
|
|
|
if (s.isEmpty()) {
|
|
|
|
throw new UnsupportedOperationException("String value is empty");
|
|
|
|
} else {
|
|
|
|
return s.charAt(0);
|
|
|
|
}
|
2008-11-15 03:26:57 +01:00
|
|
|
}
|
2008-09-01 05:13:32 +02:00
|
|
|
|
2009-04-03 23:24:38 +02:00
|
|
|
@Override
|
|
|
|
public int hashCode() {
|
2009-09-23 20:54:01 +02:00
|
|
|
if (value == null) {
|
|
|
|
return 31;
|
|
|
|
}
|
|
|
|
// Using recommended hashing algorithm from Effective Java for longs and doubles
|
|
|
|
if (isIntegral(this)) {
|
|
|
|
long value = getAsNumber().longValue();
|
|
|
|
return (int) (value ^ (value >>> 32));
|
|
|
|
}
|
2011-09-09 10:01:51 +02:00
|
|
|
if (value instanceof Number) {
|
2009-09-23 20:54:01 +02:00
|
|
|
long value = Double.doubleToLongBits(getAsNumber().doubleValue());
|
|
|
|
return (int) (value ^ (value >>> 32));
|
|
|
|
}
|
|
|
|
return value.hashCode();
|
2009-04-03 23:24:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean equals(Object obj) {
|
2009-08-18 20:07:25 +02:00
|
|
|
if (this == obj) {
|
|
|
|
return true;
|
|
|
|
}
|
2009-10-09 00:03:08 +02:00
|
|
|
if (obj == null || getClass() != obj.getClass()) {
|
2009-08-18 20:07:25 +02:00
|
|
|
return false;
|
|
|
|
}
|
2009-04-03 23:24:38 +02:00
|
|
|
JsonPrimitive other = (JsonPrimitive)obj;
|
|
|
|
if (value == null) {
|
2009-08-18 20:07:25 +02:00
|
|
|
return other.value == null;
|
|
|
|
}
|
2009-09-23 20:54:01 +02:00
|
|
|
if (isIntegral(this) && isIntegral(other)) {
|
|
|
|
return getAsNumber().longValue() == other.getAsNumber().longValue();
|
|
|
|
}
|
2011-09-09 10:01:51 +02:00
|
|
|
if (value instanceof Number && other.value instanceof Number) {
|
2011-02-15 01:14:20 +01:00
|
|
|
double a = getAsNumber().doubleValue();
|
2011-04-05 00:09:51 +02:00
|
|
|
// Java standard types other than double return true for two NaN. So, need
|
|
|
|
// special handling for double.
|
2011-02-15 01:14:20 +01:00
|
|
|
double b = other.getAsNumber().doubleValue();
|
|
|
|
return a == b || (Double.isNaN(a) && Double.isNaN(b));
|
2009-09-23 20:54:01 +02:00
|
|
|
}
|
2009-08-18 20:07:25 +02:00
|
|
|
return value.equals(other.value);
|
2009-10-09 00:03:08 +02:00
|
|
|
}
|
|
|
|
|
2009-09-23 20:54:01 +02:00
|
|
|
/**
|
2009-10-09 00:03:08 +02:00
|
|
|
* Returns true if the specified number is an integral type
|
|
|
|
* (Long, Integer, Short, Byte, BigInteger)
|
2009-09-23 20:54:01 +02:00
|
|
|
*/
|
|
|
|
private static boolean isIntegral(JsonPrimitive primitive) {
|
|
|
|
if (primitive.value instanceof Number) {
|
|
|
|
Number number = (Number) primitive.value;
|
2009-10-09 00:03:08 +02:00
|
|
|
return number instanceof BigInteger || number instanceof Long || number instanceof Integer
|
2011-04-14 04:42:47 +02:00
|
|
|
|| number instanceof Short || number instanceof Byte;
|
2009-09-23 20:54:01 +02:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2008-09-01 05:13:32 +02:00
|
|
|
}
|