Added a new API method nullSafe() in TypeAdapter that can be used to avoid boilerplate handling of nulls in a type adapter.
This commit is contained in:
parent
538b7ca172
commit
91be944022
@ -16,17 +16,19 @@
|
||||
|
||||
package com.google.gson;
|
||||
|
||||
import com.google.gson.internal.bind.JsonElementWriter;
|
||||
import com.google.gson.internal.bind.JsonTreeReader;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
import com.google.gson.internal.bind.JsonElementWriter;
|
||||
import com.google.gson.internal.bind.JsonTreeReader;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
/**
|
||||
* Converts between Java objects and JSON. Applications use type adapters both
|
||||
* for customizing types' JSON forms, and for JSON conversions.
|
||||
@ -135,6 +137,63 @@ public abstract class TypeAdapter<T> {
|
||||
write(writer, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* This wrapper method is used to make a type adapter null tolerant. In general, a
|
||||
* type adapter is required to handle nulls in write and read methods. Here is how this
|
||||
* is typically done:<br>
|
||||
* <pre>{@code
|
||||
Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
|
||||
new TypeAdapter<Foo>() {
|
||||
public Foo read(JsonReader in) throws IOException {
|
||||
if (in.peek() == JsonToken.NULL) {
|
||||
in.nextNull();
|
||||
return null;
|
||||
}
|
||||
// read a Foo from in and return it
|
||||
}
|
||||
public void write(JsonWriter out, Foo src) throws IOException {
|
||||
if (src == null) {
|
||||
out.nullValue();
|
||||
return;
|
||||
}
|
||||
// write src as JSON to out
|
||||
}
|
||||
).create();
|
||||
* }</pre>
|
||||
* You can avoid this boilerplate handling of nulls by wrapping your type adapter with
|
||||
* {@link #nullSafe(TypeAdapter)} method. Here is how we will rewrite the above example:
|
||||
* <pre>{@code
|
||||
Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
|
||||
TypeAdapter.nullSafe(new TypeAdapter<Foo>() {
|
||||
public Foo read(JsonReader in) throws IOException {
|
||||
// read a Foo from in and return it
|
||||
}
|
||||
public void write(JsonWriter out, Foo src) throws IOException {
|
||||
// write src as JSON to out
|
||||
}
|
||||
)).create();
|
||||
* }</pre>
|
||||
* Note that we didn't need to check for nulls in our type adapter after we used nullSafe.
|
||||
*/
|
||||
public static <T> TypeAdapter<T> nullSafe(final TypeAdapter<T> typeAdapter) {
|
||||
return new TypeAdapter<T>() {
|
||||
@Override public void write(JsonWriter out, T value) throws IOException {
|
||||
if (value == null) {
|
||||
out.nullValue();
|
||||
} else {
|
||||
typeAdapter.write(out, value);
|
||||
}
|
||||
}
|
||||
@Override public T read(JsonReader reader) throws IOException {
|
||||
if (reader.peek() == JsonToken.NULL) {
|
||||
reader.nextNull();
|
||||
return null;
|
||||
}
|
||||
return typeAdapter.read(reader);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts {@code value} to a JSON document. Unlike Gson's similar {@link
|
||||
* Gson#toJson(Object) toJson} method, this write is strict. Create a {@link
|
||||
|
@ -16,20 +16,24 @@
|
||||
|
||||
package com.google.gson.functional;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
public final class StreamingTypeAdaptersTest extends TestCase {
|
||||
private Gson miniGson = new GsonBuilder().create();
|
||||
private TypeAdapter<Truck> truckAdapter = miniGson.getAdapter(Truck.class);
|
||||
@ -144,6 +148,39 @@ public final class StreamingTypeAdaptersTest extends TestCase {
|
||||
assertTrue(Arrays.toString(array), Arrays.deepEquals(expected, array));
|
||||
}
|
||||
|
||||
public void testNullSafe() {
|
||||
TypeAdapter<Person> typeAdapter = new TypeAdapter<Person>() {
|
||||
@Override public Person read(JsonReader in) throws IOException {
|
||||
String[] values = in.nextString().split(",");
|
||||
return new Person(values[0], Integer.parseInt(values[1]));
|
||||
}
|
||||
public void write(JsonWriter out, Person person) throws IOException {
|
||||
out.value(person.name + "," + person.age);
|
||||
}
|
||||
};
|
||||
Gson gson = new GsonBuilder().registerTypeAdapter(
|
||||
Person.class, typeAdapter).create();
|
||||
Truck truck = new Truck();
|
||||
truck.horsePower = 1.0D;
|
||||
truck.passengers = new ArrayList<Person>();
|
||||
truck.passengers.add(null);
|
||||
try {
|
||||
gson.toJson(truck, Truck.class);
|
||||
fail();
|
||||
} catch (NullPointerException expected) {}
|
||||
String json = "{horsePower:1.0,passengers:[null,null]}";
|
||||
try {
|
||||
gson.fromJson(json, Truck.class);
|
||||
fail();
|
||||
} catch (JsonSyntaxException expected) {}
|
||||
gson = new GsonBuilder().registerTypeAdapter(
|
||||
Person.class, TypeAdapter.nullSafe(typeAdapter)).create();
|
||||
assertEquals("{\"horsePower\":1.0,\"passengers\":[null]}", gson.toJson(truck, Truck.class));
|
||||
truck = gson.fromJson(json, Truck.class);
|
||||
assertEquals(1.0D, truck.horsePower);
|
||||
assertNull(truck.passengers.get(0));
|
||||
}
|
||||
|
||||
public void testSerializeRecursive() throws IOException {
|
||||
TypeAdapter<Node> nodeAdapter = miniGson.getAdapter(Node.class);
|
||||
Node root = new Node("root");
|
||||
|
Loading…
Reference in New Issue
Block a user