Revised equals and hashcode of ObjectTypePair to ensure reference equality of object instead of value equality. Improved JavaDocs for various 1.4 API methods.
This commit is contained in:
parent
2716d96516
commit
ff74224815
|
@ -64,7 +64,10 @@ public enum FieldNamingPolicy {
|
||||||
* <li>aStringField ---> a-string-field</li>
|
* <li>aStringField ---> a-string-field</li>
|
||||||
* <li>aURL ---> a-u-r-l</li>
|
* <li>aURL ---> a-u-r-l</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
* Using dashes in JavaScript is not recommended since dash is also used for a minus sign in
|
||||||
|
* expressions. This requires that a field named with dashes is always accessed as a quoted
|
||||||
|
* property like {@code myobject['my-field']}. Accessing it as an object field
|
||||||
|
* {@code myobject.my-field} will result in an unintended javascript expression.
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
LOWER_CASE_WITH_DASHES(new LowerCamelCaseSeparatorNamingPolicy("-"));
|
LOWER_CASE_WITH_DASHES(new LowerCamelCaseSeparatorNamingPolicy("-"));
|
||||||
|
|
|
@ -187,13 +187,12 @@ public final class Gson {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method serializes the specified object into its equivalent representation as a tree of
|
* This method serializes the specified object into its equivalent representation as a tree of
|
||||||
* {JsonElement}s. This method should be used when the specified object is not a generic type.
|
* {@link JsonElement}s. This method should be used when the specified object is not a generic
|
||||||
* This method uses {@link Class#getClass()} to get the type for the specified object, but the
|
* type. This method uses {@link Class#getClass()} to get the type for the specified object, but
|
||||||
* {@code getClass()} loses the generic type information because of the Type Erasure feature
|
* the {@code getClass()} loses the generic type information because of the Type Erasure feature
|
||||||
* of Java. Note that this method works fine if the any of the object fields are of generic type,
|
* of Java. Note that this method works fine if the any of the object fields are of generic type,
|
||||||
* just the object itself should not be of a generic type. If the object is of generic type, use
|
* just the object itself should not be of a generic type. If the object is of generic type, use
|
||||||
* {@link #toJson(Object, Type)} instead. If you want to write out the object to a
|
* {@link #toJsonTree(Object, Type)} instead.
|
||||||
* {@link Writer}, use {@link #toJson(Object, Appendable)} instead.
|
|
||||||
*
|
*
|
||||||
* @param src the object for which Json representation is to be created setting for Gson
|
* @param src the object for which Json representation is to be created setting for Gson
|
||||||
* @return Json representation of {@code src}.
|
* @return Json representation of {@code src}.
|
||||||
|
@ -209,9 +208,8 @@ public final class Gson {
|
||||||
/**
|
/**
|
||||||
* This method serializes the specified object, including those of generic types, into its
|
* This method serializes the specified object, including those of generic types, into its
|
||||||
* equivalent representation as a tree of {@link JsonElement}s. This method must be used if the
|
* equivalent representation as a tree of {@link JsonElement}s. This method must be used if the
|
||||||
* specified object is a generic type. For non-generic objects, use {@link #toJson(Object)}
|
* specified object is a generic type. For non-generic objects, use {@link #toJsonTree(Object)}
|
||||||
* instead. If you want to write out the object to a {@link Appendable},
|
* instead.
|
||||||
* use {@link #toJson(Object, Type, Appendable)} instead.
|
|
||||||
*
|
*
|
||||||
* @param src the object for which JSON representation is to be created
|
* @param src the object for which JSON representation is to be created
|
||||||
* @param typeOfSrc The specific genericized type of src. You can obtain
|
* @param typeOfSrc The specific genericized type of src. You can obtain
|
||||||
|
@ -321,7 +319,7 @@ public final class Gson {
|
||||||
/**
|
/**
|
||||||
* Converts a tree of {@link JsonElement}s into its equivalent JSON representation.
|
* Converts a tree of {@link JsonElement}s into its equivalent JSON representation.
|
||||||
*
|
*
|
||||||
* @param jsonElement root of the tree of {@link JsonElement}s
|
* @param jsonElement root of a tree of {@link JsonElement}s
|
||||||
* @return JSON String representation of the tree
|
* @return JSON String representation of the tree
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
|
@ -332,9 +330,9 @@ public final class Gson {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes out the equivalent JSON for the tree of {@link JsonElement}s.
|
* Writes out the equivalent JSON for a tree of {@link JsonElement}s.
|
||||||
*
|
*
|
||||||
* @param jsonElement root of the tree of {@link JsonElement}s
|
* @param jsonElement root of a tree of {@link JsonElement}s
|
||||||
* @param writer Writer to which the Json representation needs to be written
|
* @param writer Writer to which the Json representation needs to be written
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -150,7 +150,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addAsArrayElement(ObjectTypePair elementTypePair) {
|
private void addAsArrayElement(ObjectTypePair elementTypePair) {
|
||||||
if (elementTypePair.getObj() == null) {
|
if (elementTypePair.getObject() == null) {
|
||||||
root.getAsJsonArray().add(JsonNull.createJsonNull());
|
root.getAsJsonArray().add(JsonNull.createJsonNull());
|
||||||
} else {
|
} else {
|
||||||
JsonElement childElement = getJsonElementForChild(elementTypePair);
|
JsonElement childElement = getJsonElementForChild(elementTypePair);
|
||||||
|
@ -169,7 +169,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public boolean visitUsingCustomHandler(ObjectTypePair objTypePair) {
|
public boolean visitUsingCustomHandler(ObjectTypePair objTypePair) {
|
||||||
try {
|
try {
|
||||||
Object obj = objTypePair.getObj();
|
Object obj = objTypePair.getObject();
|
||||||
Type objType = objTypePair.getType();
|
Type objType = objTypePair.getType();
|
||||||
JsonSerializer serializer = serializers.getHandlerFor(objType);
|
JsonSerializer serializer = serializers.getHandlerFor(objType);
|
||||||
if (serializer == null && obj != null) {
|
if (serializer == null && obj != null) {
|
||||||
|
@ -194,7 +194,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
|
||||||
private JsonElement invokeCustomHandler(ObjectTypePair objTypePair, JsonSerializer serializer) {
|
private JsonElement invokeCustomHandler(ObjectTypePair objTypePair, JsonSerializer serializer) {
|
||||||
start(objTypePair);
|
start(objTypePair);
|
||||||
try {
|
try {
|
||||||
return serializer.serialize(objTypePair.getObj(), objTypePair.getType(), context);
|
return serializer.serialize(objTypePair.getObject(), objTypePair.getType(), context);
|
||||||
} finally {
|
} finally {
|
||||||
end(objTypePair);
|
end(objTypePair);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,12 @@ import java.util.NoSuchElementException;
|
||||||
* A streaming parser that allows reading of multiple {@link JsonElement}s from the specified reader
|
* A streaming parser that allows reading of multiple {@link JsonElement}s from the specified reader
|
||||||
* asynchronously.
|
* asynchronously.
|
||||||
*
|
*
|
||||||
* <p>This class is thread-compatible. For some more literature on these definitions, refer to
|
* <p>This class is conditionally thread-safe (see Item 70, Effective Java second edition). To
|
||||||
* Effective Java.
|
* properly use this class across multiple threads, you will need to add some external
|
||||||
*
|
* synchronization. For example:
|
||||||
* <p>To properly use this class across multiple thread, you will need to add some external
|
|
||||||
* synchronization to your classes/thread to get this to work properly. For example:
|
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* JsonStreamParser parser = new JsonStreamParser("blah blah blah");
|
* JsonStreamParser parser = new JsonStreamParser("['first'] {'second':10} 'third'");
|
||||||
* JsonElement element;
|
* JsonElement element;
|
||||||
* synchronized (someCommonObject) {
|
* synchronized (someCommonObject) {
|
||||||
* if (parser.hasNext()) {
|
* if (parser.hasNext()) {
|
||||||
|
@ -104,6 +102,11 @@ public final class JsonStreamParser implements Iterator<JsonElement> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a {@link JsonElement} is available on the input for consumption
|
||||||
|
* @return true if a {@link JsonElement} is available on the input, false otherwise
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
|
@ -116,6 +119,11 @@ public final class JsonStreamParser implements Iterator<JsonElement> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This optional {@link Iterator} method is not relevant for stream parsing and hence is not
|
||||||
|
* implemented.
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
public void remove() {
|
public void remove() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,8 @@ final class MemoryRefStack {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ObjectTypePair stackObject : stack) {
|
for (ObjectTypePair stackObject : stack) {
|
||||||
if (stackObject.getObj() == obj.getObj() && stackObject.getType().equals(obj.getType()) ) {
|
if (stackObject.getObject() == obj.getObject()
|
||||||
|
&& stackObject.getType().equals(obj.getType()) ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ final class ObjectNavigator {
|
||||||
public void accept(Visitor visitor) {
|
public void accept(Visitor visitor) {
|
||||||
boolean visitedWithCustomHandler = visitor.visitUsingCustomHandler(objTypePair);
|
boolean visitedWithCustomHandler = visitor.visitUsingCustomHandler(objTypePair);
|
||||||
if (!visitedWithCustomHandler) {
|
if (!visitedWithCustomHandler) {
|
||||||
Object obj = objTypePair.getObj();
|
Object obj = objTypePair.getObject();
|
||||||
Object objectToVisit = (obj == null) ? visitor.getTarget() : obj;
|
Object objectToVisit = (obj == null) ? visitor.getTarget() : obj;
|
||||||
if (objectToVisit == null) {
|
if (objectToVisit == null) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,47 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009 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;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
final class ObjectTypePair {
|
/**
|
||||||
|
* A holder class for an object and its type
|
||||||
|
*
|
||||||
|
* @author Inderjeet Singh
|
||||||
|
*/
|
||||||
|
final class ObjectTypePair {
|
||||||
|
private static final int PRIME = 31;
|
||||||
|
|
||||||
private final Object obj;
|
private final Object obj;
|
||||||
private final Type type;
|
private final Type type;
|
||||||
|
|
||||||
public ObjectTypePair(Object obj, Type type) {
|
public ObjectTypePair(Object obj, Type type) {
|
||||||
this.obj = obj;
|
this.obj = obj;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
public Object getObj() {
|
|
||||||
|
public Object getObject() {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
// Not using type.hashCode() since I am not sure if the subclasses of type reimplement
|
||||||
int result = 1;
|
// hashCode() to be equal for equal types
|
||||||
result = prime * result + ((obj == null) ? 0 : obj.hashCode());
|
return ((obj == null) ? PRIME : obj.hashCode());
|
||||||
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj)
|
if (this == obj) {
|
||||||
return true;
|
return true;
|
||||||
if (obj == null)
|
}
|
||||||
|
if (obj == null) {
|
||||||
return false;
|
return false;
|
||||||
if (getClass() != obj.getClass())
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
ObjectTypePair other = (ObjectTypePair) obj;
|
ObjectTypePair other = (ObjectTypePair) obj;
|
||||||
if (this.obj == null) {
|
if (this.obj == null) {
|
||||||
if (other.obj != null)
|
if (other.obj != null) {
|
||||||
return false;
|
return false;
|
||||||
} else if (!this.obj.equals(other.obj))
|
}
|
||||||
|
} else if (this.obj != other.obj) { // Checking for reference equality
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
if (other.type != null)
|
if (other.type != null) {
|
||||||
return false;
|
return false;
|
||||||
} else if (!type.equals(other.type))
|
}
|
||||||
|
} else if (!type.equals(other.type)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,17 +62,17 @@ import java.lang.annotation.Target;
|
||||||
public @interface Expose {
|
public @interface Expose {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, the field marked with this annotation is written out in the JSON while serializing.
|
* If {@code true}, the field marked with this annotation is written out in the JSON while
|
||||||
* If false, the field marked with this annotation is skipped from the serialized output.
|
* serializing. If {@code false}, the field marked with this annotation is skipped from the
|
||||||
* Defaults to true.
|
* serialized output. Defaults to {@code true}.
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public boolean serialize() default true;
|
public boolean serialize() default true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, the field marked with this annotation is deserialized from the JSON.
|
* If {@code true}, the field marked with this annotation is deserialized from the JSON.
|
||||||
* If false, the field marked with this annotation is skipped during deserialization.
|
* If {@code false}, the field marked with this annotation is skipped during deserialization.
|
||||||
* Defaults to true.
|
* Defaults to {@code true}.
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public boolean deserialize() default true;
|
public boolean deserialize() default true;
|
||||||
|
|
|
@ -61,13 +61,12 @@ public class MemoryRefStackTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testContains() throws Exception {
|
public void testContains() throws Exception {
|
||||||
ObjectTypePair objA = new ObjectTypePair(new MockObject(), MockObject.class);
|
MockObject objA = new MockObject();
|
||||||
ObjectTypePair objB = new ObjectTypePair(new MockObject(), MockObject.class);
|
MockObject objB = new MockObject();
|
||||||
assertEquals(objA, objB);
|
assertEquals(objA, objB);
|
||||||
|
stack.push(new ObjectTypePair(objA, MockObject.class));
|
||||||
stack.push(objA);
|
assertTrue(stack.contains(new ObjectTypePair(objA, MockObject.class)));
|
||||||
assertFalse(stack.contains(objB));
|
assertFalse(stack.contains(new ObjectTypePair(objB, MockObject.class)));
|
||||||
assertTrue(stack.contains(objA));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MockObject {
|
private static class MockObject {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user