Enable serialization of nulls within Maps.
This commit is contained in:
parent
a82c400dc8
commit
b90228dcc0
@ -31,7 +31,6 @@ import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -374,7 +373,7 @@ final class DefaultTypeAdapters {
|
||||
|
||||
public JsonElement serialize(Collection src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
if (src == null) {
|
||||
return JsonNull.INSTANCE;
|
||||
return JsonNull.createJsonNull();
|
||||
}
|
||||
JsonArray array = new JsonArray();
|
||||
Type childGenericType = null;
|
||||
@ -432,13 +431,19 @@ final class DefaultTypeAdapters {
|
||||
if (typeOfSrc instanceof ParameterizedType) {
|
||||
childGenericType = new TypeInfoMap(typeOfSrc).getValueType();
|
||||
}
|
||||
for (Iterator iterator = src.entrySet().iterator(); iterator.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry) iterator.next();
|
||||
|
||||
for (Map.Entry entry : (Set<Map.Entry>) src.entrySet()) {
|
||||
Object value = entry.getValue();
|
||||
Type childType = (childGenericType == null) ?
|
||||
childType = value.getClass() : childGenericType;
|
||||
JsonElement valueElement = context.serialize(value, childType);
|
||||
map.add(entry.getKey().toString(), valueElement);
|
||||
|
||||
JsonElement valueElement;
|
||||
if (value == null) {
|
||||
valueElement = JsonNull.createJsonNull();
|
||||
} else {
|
||||
Type childType = (childGenericType == null) ?
|
||||
childType = value.getClass() : childGenericType;
|
||||
valueElement = context.serialize(value, childType);
|
||||
}
|
||||
map.add(String.valueOf(entry.getKey()), valueElement);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ final class JsonArrayDeserializationVisitor<T> extends JsonDeserializationVisito
|
||||
JsonElement jsonChild = jsonArray.get(i);
|
||||
Object child;
|
||||
|
||||
if (jsonChild == null) {
|
||||
if (jsonChild == null || jsonChild.isJsonNull()) {
|
||||
child = null;
|
||||
} else if (jsonChild instanceof JsonObject) {
|
||||
child = visitChildAsObject(arrayTypeInfo.getComponentRawType(), jsonChild);
|
||||
|
@ -17,7 +17,7 @@
|
||||
package com.google.gson;
|
||||
|
||||
/**
|
||||
* A class representing a Json null value.
|
||||
* A class representing a Json {@code null} value.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
@ -25,7 +25,19 @@ package com.google.gson;
|
||||
*/
|
||||
public final class JsonNull extends JsonElement {
|
||||
|
||||
static final JsonNull INSTANCE = new JsonNull();
|
||||
private static final JsonNull INSTANCE = new JsonNull(true);
|
||||
|
||||
/**
|
||||
* @deprecated use the creation method, {@link #createJsonNull()}, instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public JsonNull() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
private JsonNull(boolean placeholder) {
|
||||
// Prevent instantiation
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void toString(StringBuilder sb) {
|
||||
@ -46,5 +58,9 @@ public final class JsonNull extends JsonElement {
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return other instanceof JsonNull;
|
||||
}
|
||||
}
|
||||
|
||||
public static JsonNull createJsonNull() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ public final class JsonObject extends JsonElement {
|
||||
public JsonElement get(String memberName) {
|
||||
if (members.containsKey(memberName)) {
|
||||
JsonElement member = members.get(memberName);
|
||||
return member == null ? JsonNull.INSTANCE : member;
|
||||
return member == null ? JsonNull.createJsonNull() : member;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ final class JsonObjectDeserializationVisitor<T> extends JsonDeserializationVisit
|
||||
JsonElement child = json.getAsJsonObject().get(fName);
|
||||
if (child == null) {
|
||||
return true;
|
||||
} else if (JsonNull.INSTANCE.equals(child)) {
|
||||
} else if (child.isJsonNull()) {
|
||||
TypeInfo typeInfo = new TypeInfo(actualTypeOfField);
|
||||
if (!typeInfo.isPrimitive()) {
|
||||
f.set(parent, null);
|
||||
|
@ -53,7 +53,7 @@ final class JsonParser implements JsonParserConstants {
|
||||
final private JsonNull JsonNull() throws ParseException {
|
||||
Token t;
|
||||
t = jj_consume_token(NULL);
|
||||
{if (true) return JsonNull.INSTANCE;}
|
||||
{if (true) return JsonNull.createJsonNull();}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
@ -159,7 +159,7 @@ final class JsonParser implements JsonParserConstants {
|
||||
o = JsonBoolean();
|
||||
break;
|
||||
case NULL:
|
||||
jj_consume_token(NULL);
|
||||
o = JsonNull();
|
||||
break;
|
||||
default:
|
||||
jj_la1[6] = jj_gen;
|
||||
|
@ -67,7 +67,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
|
||||
public void visitArrayField(Field f, Type typeOfF, Object obj) {
|
||||
if (isFieldNull(f, obj)) {
|
||||
if (serializeNulls) {
|
||||
addChildAsElement(f, JsonNull.INSTANCE);
|
||||
addChildAsElement(f, JsonNull.createJsonNull());
|
||||
}
|
||||
} else {
|
||||
Object array = getFieldValue(f, obj);
|
||||
@ -78,7 +78,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
|
||||
public void visitObjectField(Field f, Type typeOfF, Object obj) {
|
||||
if (isFieldNull(f, obj)) {
|
||||
if (serializeNulls) {
|
||||
addChildAsElement(f, JsonNull.INSTANCE);
|
||||
addChildAsElement(f, JsonNull.createJsonNull());
|
||||
}
|
||||
} else {
|
||||
Object fieldValue = getFieldValue(f, obj);
|
||||
@ -127,7 +127,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
|
||||
JsonSerializer serializer = serializers.getHandlerFor(objType);
|
||||
if (serializer != null) {
|
||||
if (obj == null) {
|
||||
assignToRoot(JsonNull.INSTANCE);
|
||||
assignToRoot(JsonNull.createJsonNull());
|
||||
} else {
|
||||
assignToRoot(serializer.serialize(obj, objType, context));
|
||||
}
|
||||
@ -143,7 +143,7 @@ final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
|
||||
Object obj = f.get(parent);
|
||||
if (obj == null) {
|
||||
if (serializeNulls) {
|
||||
addChildAsElement(f, JsonNull.INSTANCE);
|
||||
addChildAsElement(f, JsonNull.createJsonNull());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ final class JsonTreeNavigator {
|
||||
}
|
||||
}
|
||||
visitor.endArray(array);
|
||||
} else if (element.isJsonObject()){
|
||||
} else if (element.isJsonObject()) {
|
||||
JsonObject object = element.getAsJsonObject();
|
||||
visitor.startObject(object);
|
||||
boolean isFirst = true;
|
||||
|
@ -78,7 +78,7 @@ private JsonNull JsonNull() :
|
||||
Token t;
|
||||
}
|
||||
{
|
||||
t = <NULL> { return JsonNull.INSTANCE; }
|
||||
t = <NULL> { return JsonNull.createJsonNull(); }
|
||||
}
|
||||
|
||||
private void Members(JsonObject o) :
|
||||
@ -133,7 +133,7 @@ private JsonElement JsonValue() :
|
||||
o=JsonObject() |
|
||||
o=JsonArray() |
|
||||
o=JsonBoolean() |
|
||||
"null" )
|
||||
o=JsonNull() )
|
||||
{ return o; }
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,55 @@ public class MapTest extends TestCase {
|
||||
String json = gson.toJson(map, typeOfMap);
|
||||
assertEquals("{}", json);
|
||||
}
|
||||
|
||||
public void testMapDeserializationEmpty() {
|
||||
Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType();
|
||||
Map<String, Integer> map = gson.fromJson("{}", typeOfMap);
|
||||
assertTrue(map.isEmpty());
|
||||
}
|
||||
|
||||
public void testMapSerializationWithNullValue() {
|
||||
Map<String, Integer> map = new LinkedHashMap<String, Integer>();
|
||||
map.put("abc", null);
|
||||
Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType();
|
||||
String json = gson.toJson(map, typeOfMap);
|
||||
|
||||
// Maps are represented as JSON objects, so ignoring null field
|
||||
assertEquals("{}", json);
|
||||
}
|
||||
|
||||
public void testMapDeserializationWithNullValue() {
|
||||
Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType();
|
||||
Map<String, Integer> map = gson.fromJson("{\"abc\":null}", typeOfMap);
|
||||
assertEquals(1, map.size());
|
||||
assertNull(map.get("abc"));
|
||||
}
|
||||
|
||||
public void testMapSerializationWithNullValueButSerializeNulls() {
|
||||
gson = new GsonBuilder().serializeNulls().create();
|
||||
Map<String, Integer> map = new LinkedHashMap<String, Integer>();
|
||||
map.put("abc", null);
|
||||
Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType();
|
||||
String json = gson.toJson(map, typeOfMap);
|
||||
|
||||
assertEquals("{\"abc\":null}", json);
|
||||
}
|
||||
|
||||
public void testMapSerializationWithNullKey() {
|
||||
Map<String, Integer> map = new LinkedHashMap<String, Integer>();
|
||||
map.put(null, 123);
|
||||
Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType();
|
||||
String json = gson.toJson(map, typeOfMap);
|
||||
|
||||
assertEquals("{\"null\":123}", json);
|
||||
}
|
||||
|
||||
public void testMapDeserializationWithNullKey() {
|
||||
Type typeOfMap = new TypeToken<Map<String, Integer>>() {}.getType();
|
||||
Map<String, Integer> map = gson.fromJson("{\"null\":123}", typeOfMap);
|
||||
assertEquals(1, map.size());
|
||||
assertNull(map.get(null));
|
||||
}
|
||||
|
||||
public void testParameterizedMapSubclassSerialization() {
|
||||
MyParameterizedMap<String, String> map = new MyParameterizedMap<String, String>();
|
||||
|
Loading…
Reference in New Issue
Block a user