Code cleanup and some minor performance fixes.

This commit is contained in:
Joel Leitch 2009-01-20 01:36:54 +00:00
parent 2cec661ff0
commit 6a80791f13
17 changed files with 110 additions and 124 deletions

View File

@ -454,8 +454,8 @@ final class DefaultTypeAdapters {
if (value == null) {
valueElement = JsonNull.createJsonNull();
} else {
Type childType = (childGenericType == null) ?
childType = value.getClass() : childGenericType;
Type childType = (childGenericType == null)
? value.getClass() : childGenericType;
valueElement = context.serialize(value, childType);
}
map.add(String.valueOf(entry.getKey()), valueElement);

View File

@ -26,7 +26,6 @@ import java.lang.reflect.Type;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
/**
* This is the main class for using Gson. Gson is typically used by first constructing a
@ -76,6 +75,7 @@ public final class Gson {
// constructor instead. At the minimum, mark those methods private.
private static final String NULL_STRING = "null";
// Default instances of plug-ins
static final ModifierBasedExclusionStrategy DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY =
new ModifierBasedExclusionStrategy(true, new int[] { Modifier.TRANSIENT, Modifier.STATIC });
@ -83,8 +83,6 @@ public final class Gson {
static final FieldNamingStrategy DEFAULT_NAMING_POLICY =
new SerializedNameAnnotationInterceptingNamingPolicy(new JavaFieldNamingPolicy());
static final Logger logger = Logger.getLogger(Gson.class.getName());
private final ExclusionStrategy strategy;
private final FieldNamingStrategy fieldNamingPolicy;
private final MappedObjectConstructor objectConstructor;
@ -402,15 +400,16 @@ public final class Gson {
@Override
public String toString() {
StringBuilder sb = new StringBuilder("{");
sb.append("serializeNulls:").append(serializeNulls);
sb.append(",serializers:").append(serializers);
sb.append(",deserializers:").append(deserializers);
// using the name instanceCreator instead of ObjectConstructor since the users of Gson are
// more familiar with the concept of Instance Creators. Moreover, the objectConstructor is
// just a utility class around instance creators, and its toString() only displays them.
sb.append(",instanceCreators:").append(objectConstructor);
sb.append("}");
return sb.toString();
StringBuilder sb = new StringBuilder("{")
.append("serializeNulls:").append(serializeNulls)
.append(",serializers:").append(serializers)
.append(",deserializers:").append(deserializers)
// using the name instanceCreator instead of ObjectConstructor since the users of Gson are
// more familiar with the concept of Instance Creators. Moreover, the objectConstructor is
// just a utility class around instance creators, and its toString() only displays them.
.append(",instanceCreators:").append(objectConstructor)
.append("}");
return sb.toString();
}
}

View File

@ -436,8 +436,8 @@ public final class GsonBuilder {
dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle);
}
if (dateTypeAdapter != null
&& !serializers.hasAnyHandlerFor(Date.class)
&& !deserializers.hasAnyHandlerFor(Date.class)) {
&& !serializers.hasSpecificHandlerFor(Date.class)
&& !deserializers.hasSpecificHandlerFor(Date.class)) {
serializers.register(Date.class, dateTypeAdapter);
deserializers.register(Date.class, dateTypeAdapter);
}

View File

@ -16,6 +16,7 @@
package com.google.gson;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collections;
@ -291,7 +292,7 @@ public final class JsonArray extends JsonElement implements Iterable<JsonElement
}
@Override
protected void toString(StringBuilder sb) {
protected void toString(Appendable sb) throws IOException {
sb.append('[');
boolean first = true;
for (JsonElement element : elements) {

View File

@ -35,7 +35,7 @@ final class JsonCompactFormatter implements JsonFormatter {
}
public void visitPrimitive(JsonPrimitive primitive) throws IOException {
writer.append(primitive.toString());
primitive.toString(writer);
}
public void visitNull() throws IOException {
@ -51,7 +51,7 @@ final class JsonCompactFormatter implements JsonFormatter {
if (!isFirst) {
writer.append(',');
}
writer.append(member.toString());
member.toString(writer);
}
public void visitArrayMember(JsonArray parent, JsonArray member,
@ -90,7 +90,7 @@ final class JsonCompactFormatter implements JsonFormatter {
writer.append('"');
writer.append(memberName);
writer.append("\":");
writer.append(member.toString());
member.toString(writer);
}
public void visitObjectMember(JsonObject parent, String memberName, JsonArray member,

View File

@ -17,7 +17,6 @@
package com.google.gson;
import java.lang.reflect.Type;
import java.util.logging.Logger;
/**
* Abstract data value container for the {@link ObjectNavigator.Visitor}
@ -29,8 +28,6 @@ import java.util.logging.Logger;
*/
abstract class JsonDeserializationVisitor<T> implements ObjectNavigator.Visitor {
protected static Logger logger = Logger.getLogger(JsonDeserializationVisitor.class.getName());
protected final ObjectNavigatorFactory factory;
protected final ObjectConstructor objectConstructor;
protected final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers;

View File

@ -16,6 +16,7 @@
package com.google.gson;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
@ -311,10 +312,14 @@ public abstract class JsonElement {
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
toString(sb);
return sb.toString();
try {
StringBuilder sb = new StringBuilder();
toString(sb);
return sb.toString();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
protected abstract void toString(StringBuilder sb);
protected abstract void toString(Appendable sb) throws IOException;
}

View File

@ -61,10 +61,7 @@ class JsonEscapingVisitor extends DelegatingJsonElementVisitor {
private JsonPrimitive escapeJsonPrimitive(JsonPrimitive member) {
if (member.isString()) {
String memberValue = member.getAsString();
String escapedValue = escaper.escapeJsonString(memberValue);
if (!escapedValue.equals(memberValue)) {
member.setValue(escapedValue);
}
member.setValue(escaper.escapeJsonString(memberValue));
}
return member;
}

View File

@ -16,6 +16,8 @@
package com.google.gson;
import java.io.IOException;
/**
* A class representing a Json {@code null} value.
*
@ -34,7 +36,7 @@ public final class JsonNull extends JsonElement {
}
@Override
protected void toString(StringBuilder sb) {
protected void toString(Appendable sb) throws IOException {
sb.append("null");
}

View File

@ -16,6 +16,7 @@
package com.google.gson;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
@ -189,7 +190,7 @@ public final class JsonObject extends JsonElement {
}
@Override
protected void toString(StringBuilder sb) {
protected void toString(Appendable sb) throws IOException {
sb.append('{');
boolean first = true;
for (Map.Entry<String, JsonElement> entry : members.entrySet()) {

View File

@ -16,6 +16,7 @@
package com.google.gson;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
@ -305,16 +306,13 @@ public final class JsonPrimitive extends JsonElement {
}
@Override
protected void toString(StringBuilder sb) {
if (value != null) {
if (value instanceof String) {
sb.append('"');
sb.append(value);
sb.append('"');
} else {
sb.append(value);
}
protected void toString(Appendable sb) throws IOException {
if (value instanceof String) {
sb.append('"');
sb.append((String) value);
sb.append('"');
} else {
sb.append(value.toString());
}
}

View File

@ -103,17 +103,13 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
private void addAsArrayElement(Type elementType, Object elementValue) {
if (elementValue == null) {
addNullAsArrayElement();
root.getAsJsonArray().add(JsonNull.createJsonNull());
} else {
JsonElement childElement = getJsonElementForChild(elementType, elementValue);
root.getAsJsonArray().add(childElement);
}
}
private void addNullAsArrayElement() {
root.getAsJsonArray().add(null);
}
private JsonElement getJsonElementForChild(Type fieldType, Object fieldValue) {
ObjectNavigator on = factory.create(fieldValue, fieldType);
JsonSerializationVisitor childVisitor =
@ -160,7 +156,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
}
private void assignToRoot(JsonElement newRoot) {
Preconditions.checkArgument(root == null);
Preconditions.checkNotNull(newRoot);
root = newRoot;
}

View File

@ -34,7 +34,7 @@ final class JsonTreeNavigator {
}
public void navigate(JsonElement element) throws IOException {
if (element == null || element.isJsonNull()) {
if (element.isJsonNull()) {
visitor.visitNull();
} else if (element.isJsonArray()) {
JsonArray array = element.getAsJsonArray();
@ -68,25 +68,23 @@ final class JsonTreeNavigator {
*/
private boolean visitChild(JsonObject parent, String childName, JsonElement child,
boolean isFirst) throws IOException {
if (child != null) {
if (child.isJsonNull()) {
if (visitNulls) {
visitor.visitNullObjectMember(parent, childName, isFirst);
navigate(child.getAsJsonNull());
} else { // Null value is being skipped.
return false;
}
} else if (child.isJsonArray()) {
JsonArray childAsArray = child.getAsJsonArray();
visitor.visitObjectMember(parent, childName, childAsArray, isFirst);
navigate(childAsArray);
} else if (child.isJsonObject()) {
JsonObject childAsObject = child.getAsJsonObject();
visitor.visitObjectMember(parent, childName, childAsObject, isFirst);
navigate(childAsObject);
} else { // is a JsonPrimitive
visitor.visitObjectMember(parent, childName, child.getAsJsonPrimitive(), isFirst);
if (child.isJsonNull()) {
if (visitNulls) {
visitor.visitNullObjectMember(parent, childName, isFirst);
navigate(child.getAsJsonNull());
} else { // Null value is being skipped.
return false;
}
} else if (child.isJsonArray()) {
JsonArray childAsArray = child.getAsJsonArray();
visitor.visitObjectMember(parent, childName, childAsArray, isFirst);
navigate(childAsArray);
} else if (child.isJsonObject()) {
JsonObject childAsObject = child.getAsJsonObject();
visitor.visitObjectMember(parent, childName, childAsObject, isFirst);
navigate(childAsObject);
} else { // is a JsonPrimitive
visitor.visitObjectMember(parent, childName, child.getAsJsonPrimitive(), isFirst);
}
return true;
}
@ -95,9 +93,9 @@ final class JsonTreeNavigator {
* Returns true if the child was visited, false if it was skipped.
*/
private void visitChild(JsonArray parent, JsonElement child, boolean isFirst) throws IOException {
if (child == null || child.isJsonNull()) {
if (child.isJsonNull()) {
visitor.visitNullArrayMember(parent, isFirst);
navigate(null);
navigate(child);
} else if (child.isJsonArray()) {
JsonArray childAsArray = child.getAsJsonArray();
visitor.visitArrayMember(parent, childAsArray, isFirst);

View File

@ -35,15 +35,15 @@ import java.util.logging.Logger;
* @author Joel Leitch
*/
final class MappedObjectConstructor implements ObjectConstructor {
private final Logger log = Logger.getLogger(getClass().getName());
private static final Logger log = Logger.getLogger(MappedObjectConstructor.class.getName());
private final ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreatorMap =
new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
@SuppressWarnings("unchecked")
public <T> T construct(Type typeOfT) {
if (instanceCreatorMap.hasAnyHandlerFor(typeOfT)) {
InstanceCreator<T> creator = (InstanceCreator<T>) instanceCreatorMap.getHandlerFor(typeOfT);
InstanceCreator<T> creator = (InstanceCreator<T>) instanceCreatorMap.getHandlerFor(typeOfT);
if (creator != null) {
return creator.createInstance(typeOfT);
}
return (T) constructWithNoArgConstructor(typeOfT);

View File

@ -16,40 +16,46 @@
package com.google.gson;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A map that provides ability to associate handlers for a specific type or all of its sub-types
*
* A map that provides ability to associate handlers for a specific type or all
* of its sub-types
*
* @author Inderjeet Singh
* @author Joel Leitch
*
* @param <T> The handler that will be looked up by type
*
* @param <T>
* The handler that will be looked up by type
*/
final class ParameterizedTypeHandlerMap<T> {
private static final Logger logger =
Logger.getLogger(ParameterizedTypeHandlerMap.class.getName());
private final Map<Type, T> map = new HashMap<Type, T>();
private boolean modifiable = true;
public synchronized void register(Type typeOfT, T value) {
if (!modifiable) {
throw new IllegalStateException("Attempted to modify an unmodifiable map.");
throw new IllegalStateException(
"Attempted to modify an unmodifiable map.");
}
if (hasSpecificHandlerFor(typeOfT)) {
Gson.logger.log(Level.WARNING, "Overriding the existing type handler for " + typeOfT);
logger.log(Level.WARNING,
"Overriding the existing type handler for " + typeOfT);
}
map.put(typeOfT, value);
}
public synchronized void registerIfAbsent(ParameterizedTypeHandlerMap<T> other) {
if (!modifiable) {
throw new IllegalStateException("Attempted to modify an unmodifiable map.");
throw new IllegalStateException(
"Attempted to modify an unmodifiable map.");
}
for (Map.Entry<Type, T> entry : other.entrySet()) {
if (!map.containsKey(entry.getKey())) {
@ -60,7 +66,8 @@ final class ParameterizedTypeHandlerMap<T> {
public synchronized void registerIfAbsent(Type typeOfT, T value) {
if (!modifiable) {
throw new IllegalStateException("Attempted to modify an unmodifiable map.");
throw new IllegalStateException(
"Attempted to modify an unmodifiable map.");
}
if (!map.containsKey(typeOfT)) {
register(typeOfT, value);
@ -72,18 +79,15 @@ final class ParameterizedTypeHandlerMap<T> {
}
public synchronized T getHandlerFor(Type type) {
T handler = getRawHandlerFor(type);
Type rawType = type;
if (handler == null && type instanceof ParameterizedType) {
// a handler for a non-generic version may be registered, so use that
rawType = ((ParameterizedType)type).getRawType();
handler = map.get(rawType);
}
// Check for map or collection
T handler = map.get(type);
if (handler == null) {
if (rawType instanceof Class) {
Class<?> rawClass = (Class<?>) rawType;
Class<?> rawClass = TypeUtils.toRawClass(type);
if (rawClass != type) {
handler = getHandlerFor(rawClass);
}
// Check for map or collection
if (handler == null) {
if (Map.class.isAssignableFrom(rawClass)) {
handler = map.get(Map.class);
} else if (Collection.class.isAssignableFrom(rawClass)) {
@ -95,27 +99,6 @@ final class ParameterizedTypeHandlerMap<T> {
}
return handler;
}
private synchronized T getRawHandlerFor(Type type) {
if (type instanceof Map) {
return map.get(Map.class);
} else if (type instanceof Collection) {
return map.get(Collection.class);
} else {
T handler = map.get(type);
if (handler == null) {
Class<?> rawClass = TypeUtils.toRawClass(type);
if (rawClass != type) {
handler = getHandlerFor(rawClass);
}
}
return handler;
}
}
public synchronized boolean hasAnyHandlerFor(Type type) {
return getHandlerFor(type) != null;
}
public synchronized boolean hasSpecificHandlerFor(Type type) {
return map.containsKey(type);
@ -132,7 +115,7 @@ final class ParameterizedTypeHandlerMap<T> {
public synchronized Set<Map.Entry<Type, T>> entrySet() {
return map.entrySet();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("{");
@ -148,7 +131,7 @@ final class ParameterizedTypeHandlerMap<T> {
}
return sb.toString();
}
private String typeToString(Type type) {
return TypeUtils.toRawClass(type).getSimpleName();
}

View File

@ -39,7 +39,7 @@ public class ParameterizedTypeHandlerMapTest extends TestCase {
public void testNullMap() throws Exception {
assertFalse(paramMap.hasSpecificHandlerFor(String.class));
assertFalse(paramMap.hasAnyHandlerFor(String.class));
assertNull(paramMap.getHandlerFor(String.class));
assertNull(paramMap.getHandlerFor(String.class));
}
@ -50,8 +50,8 @@ public class ParameterizedTypeHandlerMapTest extends TestCase {
assertFalse(paramMap.hasSpecificHandlerFor(specificType));
assertTrue(paramMap.hasSpecificHandlerFor(List.class));
assertTrue(paramMap.hasAnyHandlerFor(specificType));
assertTrue(paramMap.hasAnyHandlerFor(List.class));
assertNotNull(paramMap.getHandlerFor(specificType));
assertNotNull(paramMap.getHandlerFor(List.class));
assertEquals(handler, paramMap.getHandlerFor(specificType));
}
@ -62,8 +62,8 @@ public class ParameterizedTypeHandlerMapTest extends TestCase {
assertTrue(paramMap.hasSpecificHandlerFor(specificType));
assertFalse(paramMap.hasSpecificHandlerFor(List.class));
assertTrue(paramMap.hasAnyHandlerFor(specificType));
assertFalse(paramMap.hasAnyHandlerFor(List.class));
assertNotNull(paramMap.getHandlerFor(specificType));
assertNull(paramMap.getHandlerFor(List.class));
assertEquals(handler, paramMap.getHandlerFor(specificType));
}

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gson.functional;
import com.google.gson.Gson;
@ -82,6 +83,14 @@ public class ArrayTest extends TestCase {
assertEquals(expected[i], target[i]);
}
}
public void testNullsInArrayWithSerializeNullPropertySetSerialization() {
gson = new GsonBuilder().serializeNulls().create();
String[] array = {"foo", null, "bar"};
String expected = "[\"foo\",null,\"bar\"]";
String json = gson.toJson(array);
assertEquals(expected, json);
}
public void testArrayOfStringsSerialization() {
String[] target = {"Hello", "World"};