Parsing numbers lazily as a performance enhancement.
This avoids needing to parse number if the equivalent object field doesn't exist. It also avoids the performance penalty of trying to parse it eagerly as a big decimal, float etc.
This commit is contained in:
parent
a21ddcbe2f
commit
824635158c
|
@ -31,6 +31,7 @@ import java.math.BigInteger;
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public final class JsonPrimitive extends JsonElement {
|
public final class JsonPrimitive extends JsonElement {
|
||||||
|
|
||||||
private static final Class<?>[] PRIMITIVE_TYPES = { int.class, long.class, short.class,
|
private static final Class<?>[] PRIMITIVE_TYPES = { int.class, long.class, short.class,
|
||||||
float.class, double.class, byte.class, boolean.class, char.class, Integer.class, Long.class,
|
float.class, double.class, byte.class, boolean.class, char.class, Integer.class, Long.class,
|
||||||
Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class };
|
Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class };
|
||||||
|
@ -154,24 +155,7 @@ public final class JsonPrimitive extends JsonElement {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Number getAsNumber() {
|
public Number getAsNumber() {
|
||||||
return value instanceof String ? stringToNumber((String) value) : (Number) value;
|
return value instanceof String ? new LazilyParsedNumber((String) value) : (Number) value;
|
||||||
}
|
|
||||||
|
|
||||||
static Number stringToNumber(String value) {
|
|
||||||
try {
|
|
||||||
long longValue = Long.parseLong(value);
|
|
||||||
if (longValue >= Integer.MIN_VALUE && longValue <= Integer.MAX_VALUE) {
|
|
||||||
return (int) longValue;
|
|
||||||
}
|
|
||||||
return longValue;
|
|
||||||
} catch (NumberFormatException ignored) {
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return new BigDecimal(value);
|
|
||||||
} catch (NumberFormatException ignored) {
|
|
||||||
return Double.parseDouble(value); // probably NaN, -Infinity or Infinity
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
55
gson/src/main/java/com/google/gson/LazilyParsedNumber.java
Normal file
55
gson/src/main/java/com/google/gson/LazilyParsedNumber.java
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2011 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class holds a number value that is lazily converted to a specific number type
|
||||||
|
*
|
||||||
|
* @author Inderjeet Singh
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
final class LazilyParsedNumber extends Number {
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
LazilyParsedNumber(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int intValue() {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long longValue() {
|
||||||
|
return Long.parseLong(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float floatValue() {
|
||||||
|
return Float.parseFloat(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double doubleValue() {
|
||||||
|
return Double.parseDouble(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -62,7 +62,7 @@ final class Streams {
|
||||||
return new JsonPrimitive(reader.nextString());
|
return new JsonPrimitive(reader.nextString());
|
||||||
case NUMBER:
|
case NUMBER:
|
||||||
String number = reader.nextString();
|
String number = reader.nextString();
|
||||||
return new JsonPrimitive(JsonPrimitive.stringToNumber(number));
|
return new JsonPrimitive(new LazilyParsedNumber(number));
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
return new JsonPrimitive(reader.nextBoolean());
|
return new JsonPrimitive(reader.nextBoolean());
|
||||||
case NULL:
|
case NULL:
|
||||||
|
|
|
@ -206,12 +206,13 @@ public class ArrayTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testArrayOfPrimitivesAsObjectsDeserialization() throws Exception {
|
public void testArrayOfPrimitivesAsObjectsDeserialization() throws Exception {
|
||||||
String json = "[1,'abc',0.3,5]";
|
String json = "[1,'abc',0.3,1.1,5]";
|
||||||
Object[] objs = gson.fromJson(json, Object[].class);
|
Object[] objs = gson.fromJson(json, Object[].class);
|
||||||
assertEquals(1, objs[0]);
|
assertEquals(1, ((Number)objs[0]).intValue());
|
||||||
assertEquals("abc", objs[1]);
|
assertEquals("abc", objs[1]);
|
||||||
assertEquals(new BigDecimal("0.3"), objs[2]);
|
assertEquals(0.3, ((Number)objs[2]).doubleValue());
|
||||||
assertEquals(5, objs[3]);
|
assertEquals(new BigDecimal("1.1"), new BigDecimal(objs[3].toString()));
|
||||||
|
assertEquals(5, ((Number)objs[4]).shortValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testArrayOfObjectsWithoutTypeInfoDeserialization() throws Exception {
|
public void testArrayOfObjectsWithoutTypeInfoDeserialization() throws Exception {
|
||||||
|
|
|
@ -127,7 +127,7 @@ public class ParameterizedTypesTest extends TestCase {
|
||||||
MyParameterizedType<Integer> src = new MyParameterizedType<Integer>(10);
|
MyParameterizedType<Integer> src = new MyParameterizedType<Integer>(10);
|
||||||
String json = MyParameterizedTypeAdapter.<Integer>getExpectedJson(src);
|
String json = MyParameterizedTypeAdapter.<Integer>getExpectedJson(src);
|
||||||
MyParameterizedType<Integer> intTarget = gson.fromJson(json, ptIntegerType);
|
MyParameterizedType<Integer> intTarget = gson.fromJson(json, ptIntegerType);
|
||||||
assertEquals(10, (int) intTarget.value);
|
assertEquals(10, ((Number)intTarget.value).intValue());
|
||||||
|
|
||||||
MyParameterizedType<String> srcStr = new MyParameterizedType<String>("abc");
|
MyParameterizedType<String> srcStr = new MyParameterizedType<String>("abc");
|
||||||
json = MyParameterizedTypeAdapter.<String>getExpectedJson(srcStr);
|
json = MyParameterizedTypeAdapter.<String>getExpectedJson(srcStr);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user