github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgRpc/kmgRpcJava/java/src/com/google/gson/JsonPrimitive.java (about) 1 /* 2 * Copyright (C) 2008 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.gson; 18 19 import java.math.BigDecimal; 20 import java.math.BigInteger; 21 22 import com.google.gson.internal.$Gson$Preconditions; 23 import com.google.gson.internal.LazilyParsedNumber; 24 25 /** 26 * A class representing a Json primitive value. A primitive value 27 * is either a String, a Java primitive, or a Java primitive 28 * wrapper type. 29 * 30 * @author Inderjeet Singh 31 * @author Joel Leitch 32 */ 33 public final class JsonPrimitive extends JsonElement { 34 35 private static final Class<?>[] PRIMITIVE_TYPES = { int.class, long.class, short.class, 36 float.class, double.class, byte.class, boolean.class, char.class, Integer.class, Long.class, 37 Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class }; 38 39 private Object value; 40 41 /** 42 * Create a primitive containing a boolean value. 43 * 44 * @param bool the value to create the primitive with. 45 */ 46 public JsonPrimitive(Boolean bool) { 47 setValue(bool); 48 } 49 50 /** 51 * Create a primitive containing a {@link Number}. 52 * 53 * @param number the value to create the primitive with. 54 */ 55 public JsonPrimitive(Number number) { 56 setValue(number); 57 } 58 59 /** 60 * Create a primitive containing a String value. 61 * 62 * @param string the value to create the primitive with. 63 */ 64 public JsonPrimitive(String string) { 65 setValue(string); 66 } 67 68 /** 69 * Create a primitive containing a character. The character is turned into a one character String 70 * since Json only supports String. 71 * 72 * @param c the value to create the primitive with. 73 */ 74 public JsonPrimitive(Character c) { 75 setValue(c); 76 } 77 78 /** 79 * Create a primitive using the specified Object. It must be an instance of {@link Number}, a 80 * Java primitive type, or a String. 81 * 82 * @param primitive the value to create the primitive with. 83 */ 84 JsonPrimitive(Object primitive) { 85 setValue(primitive); 86 } 87 88 @Override 89 JsonPrimitive deepCopy() { 90 return this; 91 } 92 93 void setValue(Object primitive) { 94 if (primitive instanceof Character) { 95 // convert characters to strings since in JSON, characters are represented as a single 96 // character string 97 char c = ((Character) primitive).charValue(); 98 this.value = String.valueOf(c); 99 } else { 100 $Gson$Preconditions.checkArgument(primitive instanceof Number 101 || isPrimitiveOrString(primitive)); 102 this.value = primitive; 103 } 104 } 105 106 /** 107 * Check whether this primitive contains a boolean value. 108 * 109 * @return true if this primitive contains a boolean value, false otherwise. 110 */ 111 public boolean isBoolean() { 112 return value instanceof Boolean; 113 } 114 115 /** 116 * convenience method to get this element as a {@link Boolean}. 117 * 118 * @return get this element as a {@link Boolean}. 119 */ 120 @Override 121 Boolean getAsBooleanWrapper() { 122 return (Boolean) value; 123 } 124 125 /** 126 * convenience method to get this element as a boolean value. 127 * 128 * @return get this element as a primitive boolean value. 129 */ 130 @Override 131 public boolean getAsBoolean() { 132 if (isBoolean()) { 133 return getAsBooleanWrapper().booleanValue(); 134 } else { 135 // Check to see if the value as a String is "true" in any case. 136 return Boolean.parseBoolean(getAsString()); 137 } 138 } 139 140 /** 141 * Check whether this primitive contains a Number. 142 * 143 * @return true if this primitive contains a Number, false otherwise. 144 */ 145 public boolean isNumber() { 146 return value instanceof Number; 147 } 148 149 /** 150 * convenience method to get this element as a Number. 151 * 152 * @return get this element as a Number. 153 * @throws NumberFormatException if the value contained is not a valid Number. 154 */ 155 @Override 156 public Number getAsNumber() { 157 return value instanceof String ? new LazilyParsedNumber((String) value) : (Number) value; 158 } 159 160 /** 161 * Check whether this primitive contains a String value. 162 * 163 * @return true if this primitive contains a String value, false otherwise. 164 */ 165 public boolean isString() { 166 return value instanceof String; 167 } 168 169 /** 170 * convenience method to get this element as a String. 171 * 172 * @return get this element as a String. 173 */ 174 @Override 175 public String getAsString() { 176 if (isNumber()) { 177 return getAsNumber().toString(); 178 } else if (isBoolean()) { 179 return getAsBooleanWrapper().toString(); 180 } else { 181 return (String) value; 182 } 183 } 184 185 /** 186 * convenience method to get this element as a primitive double. 187 * 188 * @return get this element as a primitive double. 189 * @throws NumberFormatException if the value contained is not a valid double. 190 */ 191 @Override 192 public double getAsDouble() { 193 return isNumber() ? getAsNumber().doubleValue() : Double.parseDouble(getAsString()); 194 } 195 196 /** 197 * convenience method to get this element as a {@link BigDecimal}. 198 * 199 * @return get this element as a {@link BigDecimal}. 200 * @throws NumberFormatException if the value contained is not a valid {@link BigDecimal}. 201 */ 202 @Override 203 public BigDecimal getAsBigDecimal() { 204 return value instanceof BigDecimal ? (BigDecimal) value : new BigDecimal(value.toString()); 205 } 206 207 /** 208 * convenience method to get this element as a {@link BigInteger}. 209 * 210 * @return get this element as a {@link BigInteger}. 211 * @throws NumberFormatException if the value contained is not a valid {@link BigInteger}. 212 */ 213 @Override 214 public BigInteger getAsBigInteger() { 215 return value instanceof BigInteger ? 216 (BigInteger) value : new BigInteger(value.toString()); 217 } 218 219 /** 220 * convenience method to get this element as a float. 221 * 222 * @return get this element as a float. 223 * @throws NumberFormatException if the value contained is not a valid float. 224 */ 225 @Override 226 public float getAsFloat() { 227 return isNumber() ? getAsNumber().floatValue() : Float.parseFloat(getAsString()); 228 } 229 230 /** 231 * convenience method to get this element as a primitive long. 232 * 233 * @return get this element as a primitive long. 234 * @throws NumberFormatException if the value contained is not a valid long. 235 */ 236 @Override 237 public long getAsLong() { 238 return isNumber() ? getAsNumber().longValue() : Long.parseLong(getAsString()); 239 } 240 241 /** 242 * convenience method to get this element as a primitive short. 243 * 244 * @return get this element as a primitive short. 245 * @throws NumberFormatException if the value contained is not a valid short value. 246 */ 247 @Override 248 public short getAsShort() { 249 return isNumber() ? getAsNumber().shortValue() : Short.parseShort(getAsString()); 250 } 251 252 /** 253 * convenience method to get this element as a primitive integer. 254 * 255 * @return get this element as a primitive integer. 256 * @throws NumberFormatException if the value contained is not a valid integer. 257 */ 258 @Override 259 public int getAsInt() { 260 return isNumber() ? getAsNumber().intValue() : Integer.parseInt(getAsString()); 261 } 262 263 @Override 264 public byte getAsByte() { 265 return isNumber() ? getAsNumber().byteValue() : Byte.parseByte(getAsString()); 266 } 267 268 @Override 269 public char getAsCharacter() { 270 return getAsString().charAt(0); 271 } 272 273 private static boolean isPrimitiveOrString(Object target) { 274 if (target instanceof String) { 275 return true; 276 } 277 278 Class<?> classOfPrimitive = target.getClass(); 279 for (Class<?> standardPrimitive : PRIMITIVE_TYPES) { 280 if (standardPrimitive.isAssignableFrom(classOfPrimitive)) { 281 return true; 282 } 283 } 284 return false; 285 } 286 287 @Override 288 public int hashCode() { 289 if (value == null) { 290 return 31; 291 } 292 // Using recommended hashing algorithm from Effective Java for longs and doubles 293 if (isIntegral(this)) { 294 long value = getAsNumber().longValue(); 295 return (int) (value ^ (value >>> 32)); 296 } 297 if (value instanceof Number) { 298 long value = Double.doubleToLongBits(getAsNumber().doubleValue()); 299 return (int) (value ^ (value >>> 32)); 300 } 301 return value.hashCode(); 302 } 303 304 @Override 305 public boolean equals(Object obj) { 306 if (this == obj) { 307 return true; 308 } 309 if (obj == null || getClass() != obj.getClass()) { 310 return false; 311 } 312 JsonPrimitive other = (JsonPrimitive)obj; 313 if (value == null) { 314 return other.value == null; 315 } 316 if (isIntegral(this) && isIntegral(other)) { 317 return getAsNumber().longValue() == other.getAsNumber().longValue(); 318 } 319 if (value instanceof Number && other.value instanceof Number) { 320 double a = getAsNumber().doubleValue(); 321 // Java standard types other than double return true for two NaN. So, need 322 // special handling for double. 323 double b = other.getAsNumber().doubleValue(); 324 return a == b || (Double.isNaN(a) && Double.isNaN(b)); 325 } 326 return value.equals(other.value); 327 } 328 329 /** 330 * Returns true if the specified number is an integral type 331 * (Long, Integer, Short, Byte, BigInteger) 332 */ 333 private static boolean isIntegral(JsonPrimitive primitive) { 334 if (primitive.value instanceof Number) { 335 Number number = (Number) primitive.value; 336 return number instanceof BigInteger || number instanceof Long || number instanceof Integer 337 || number instanceof Short || number instanceof Byte; 338 } 339 return false; 340 } 341 }