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  }