Hide toJson/fromJson APIs for the 2.1 release.

This commit is contained in:
Jesse Wilson 2011-12-21 21:30:18 +00:00
parent dd9ae67af5
commit b28e518c7e
3 changed files with 88 additions and 62 deletions

View File

@ -16,18 +16,17 @@
package com.google.gson;
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;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
/**
* Converts Java objects to and from JSON.
@ -94,28 +93,30 @@ import com.google.gson.stream.JsonWriter;
* Gson gson = builder.create();
* }</pre>
*
* <h3>JSON Conversion</h3>
* <p>A type adapter registered with Gson is automatically invoked while serializing
* or deserializing JSON. However, you can also use type adapters directly to serialize
* and deserialize JSON. Here is an example for deserialization: <pre> {@code
*
* String json = "{'origin':'0,0','points':['1,2','3,4']}";
* TypeAdapter<Graph> graphAdapter = gson.getAdapter(Graph.class);
* Graph graph = graphAdapter.fromJson(json);
* }</pre>
* And an example for serialization: <pre> {@code
*
* Graph graph = new Graph(...);
* TypeAdapter<Graph> graphAdapter = gson.getAdapter(Graph.class);
* String json = graphAdapter.toJson(graph);
* }</pre>
*
* <p>Type adapters are <strong>type-specific</strong>. For example, a {@code
* TypeAdapter<Date>} can convert {@code Date} instances to JSON and JSON to
* instances of {@code Date}, but cannot convert any other types.
*
* @since 2.1
*/
// non-Javadoc:
//
// <h3>JSON Conversion</h3>
// <p>A type adapter registered with Gson is automatically invoked while serializing
// or deserializing JSON. However, you can also use type adapters directly to serialize
// and deserialize JSON. Here is an example for deserialization: <pre> {@code
//
// String json = "{'origin':'0,0','points':['1,2','3,4']}";
// TypeAdapter<Graph> graphAdapter = gson.getAdapter(Graph.class);
// Graph graph = graphAdapter.fromJson(json);
// }</pre>
// And an example for serialization: <pre> {@code
//
// Graph graph = new Graph(...);
// TypeAdapter<Graph> graphAdapter = gson.getAdapter(Graph.class);
// String json = graphAdapter.toJson(graph);
// }</pre>
//
// <p>Type adapters are <strong>type-specific</strong>. For example, a {@code
// TypeAdapter<Date>} can convert {@code Date} instances to JSON and JSON to
// instances of {@code Date}, but cannot convert any other types.
//
public abstract class TypeAdapter<T> {
/**
@ -136,7 +137,7 @@ public abstract class TypeAdapter<T> {
*
* @param value the Java object to convert. May be null.
*/
public final void toJson(Writer out, T value) throws IOException {
/*public*/ final void toJson(Writer out, T value) throws IOException {
JsonWriter writer = new JsonWriter(out);
write(writer, value);
}
@ -181,7 +182,7 @@ public abstract class TypeAdapter<T> {
* }</pre>
* Note that we didn't need to check for nulls in our type adapter after we used nullSafe.
*/
public TypeAdapter<T> nullSafe() {
public final TypeAdapter<T> nullSafe() {
return new TypeAdapter<T>() {
@Override public void write(JsonWriter out, T value) throws IOException {
if (value == null) {
@ -209,7 +210,7 @@ public abstract class TypeAdapter<T> {
*
* @param value the Java object to convert. May be null.
*/
public final String toJson(T value) throws IOException {
/*public*/ final String toJson(T value) throws IOException {
StringWriter stringWriter = new StringWriter();
toJson(stringWriter, value);
return stringWriter.toString();
@ -221,7 +222,7 @@ public abstract class TypeAdapter<T> {
* @param value the Java object to convert. May be null.
* @return the converted JSON tree. May be {@link JsonNull}.
*/
public JsonElement toJsonTree(T value) {
/*public*/ final JsonElement toJsonTree(T value) {
try {
JsonElementWriter jsonWriter = new JsonElementWriter();
jsonWriter.setLenient(true);
@ -248,7 +249,7 @@ public abstract class TypeAdapter<T> {
*
* @return the converted Java object. May be null.
*/
public final T fromJson(Reader in) throws IOException {
/*public*/ final T fromJson(Reader in) throws IOException {
JsonReader reader = new JsonReader(in);
reader.setLenient(true); // TODO: non-lenient?
return read(reader);
@ -262,7 +263,7 @@ public abstract class TypeAdapter<T> {
*
* @return the converted Java object. May be null.
*/
public final T fromJson(String json) throws IOException {
/*public*/ final T fromJson(String json) throws IOException {
return fromJson(new StringReader(json));
}
@ -271,7 +272,7 @@ public abstract class TypeAdapter<T> {
*
* @param jsonTree the Java object to convert. May be {@link JsonNull}.
*/
public T fromJsonTree(JsonElement jsonTree) {
/*public*/ final T fromJsonTree(JsonElement jsonTree) {
try {
JsonReader jsonReader = new JsonTreeReader(jsonTree);
jsonReader.setLenient(true);

View File

@ -18,6 +18,7 @@ package com.google.gson.internal.bind;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonIOException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
@ -215,7 +216,7 @@ public final class MapTypeAdapterFactory implements TypeAdapter.Factory {
List<V> values = new ArrayList<V>(map.size());
for (Map.Entry<K, V> entry : map.entrySet()) {
JsonElement keyElement = keyTypeAdapter.toJsonTree(entry.getKey());
JsonElement keyElement = toJsonTree(keyTypeAdapter, entry.getKey());
keys.add(keyElement);
values.add(entry.getValue());
hasComplexKeys |= keyElement.isJsonArray() || keyElement.isJsonObject();
@ -260,4 +261,16 @@ public final class MapTypeAdapterFactory implements TypeAdapter.Factory {
}
}
}
// TODO: remove this when TypeAdapter.toJsonTree() is public
private static <T> JsonElement toJsonTree(TypeAdapter<T> typeAdapter, T value) {
try {
JsonElementWriter jsonWriter = new JsonElementWriter();
jsonWriter.setLenient(true);
typeAdapter.write(jsonWriter, value);
return jsonWriter.get();
} catch (IOException e) {
throw new JsonIOException(e);
}
}
}

View File

@ -16,16 +16,6 @@
package com.google.gson.functional;
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;
@ -33,6 +23,16 @@ 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.io.StringReader;
import java.io.StringWriter;
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;
public final class StreamingTypeAdaptersTest extends TestCase {
private Gson miniGson = new GsonBuilder().create();
@ -47,13 +47,13 @@ public final class StreamingTypeAdaptersTest extends TestCase {
assertEquals("{'horsePower':300.0,"
+ "'passengers':[{'age':29,'name':'Jesse'},{'age':29,'name':'Jodie'}]}",
truckAdapter.toJson(truck).replace('\"', '\''));
toJson(truckAdapter, truck).replace('\"', '\''));
}
public void testDeserialize() throws IOException {
String json = "{'horsePower':300.0,"
+ "'passengers':[{'age':29,'name':'Jesse'},{'age':29,'name':'Jodie'}]}";
Truck truck = truckAdapter.fromJson(json);
Truck truck = fromJson(truckAdapter, json);
assertEquals(300.0, truck.horsePower);
assertEquals(Arrays.asList(new Person("Jesse", 29), new Person("Jodie", 29)), truck.passengers);
}
@ -62,11 +62,11 @@ public final class StreamingTypeAdaptersTest extends TestCase {
Truck truck = new Truck();
truck.passengers = null;
assertEquals("{'horsePower':0.0,'passengers':null}",
truckAdapter.toJson(truck).replace('\"', '\''));
toJson(truckAdapter, truck).replace('\"', '\''));
}
public void testDeserializeNullField() throws IOException {
Truck truck = truckAdapter.fromJson("{'horsePower':0.0,'passengers':null}");
Truck truck = fromJson(truckAdapter, "{'horsePower':0.0,'passengers':null}");
assertNull(truck.passengers);
}
@ -74,11 +74,11 @@ public final class StreamingTypeAdaptersTest extends TestCase {
Truck truck = new Truck();
truck.passengers = Arrays.asList((Person) null);
assertEquals("{'horsePower':0.0,'passengers':[null]}",
truckAdapter.toJson(truck).replace('\"', '\''));
toJson(truckAdapter, truck).replace('\"', '\''));
}
public void testDeserializeNullObject() throws IOException {
Truck truck = truckAdapter.fromJson("{'horsePower':0.0,'passengers':[null]}");
Truck truck = fromJson(truckAdapter, "{'horsePower':0.0,'passengers':[null]}");
assertEquals(Arrays.asList((Person) null), truck.passengers);
}
@ -87,12 +87,12 @@ public final class StreamingTypeAdaptersTest extends TestCase {
Truck truck = new Truck();
truck.passengers = Arrays.asList(new Person("Jesse", 29), new Person("Jodie", 29));
assertEquals("{'horsePower':0.0,'passengers':['Jesse','Jodie']}",
truckAdapter.toJson(truck).replace('\"', '\''));
toJson(truckAdapter, truck).replace('\"', '\''));
}
public void testDeserializeWithCustomTypeAdapter() throws IOException {
usePersonNameAdapter();
Truck truck = truckAdapter.fromJson("{'horsePower':0.0,'passengers':['Jesse','Jodie']}");
Truck truck = fromJson(truckAdapter, "{'horsePower':0.0,'passengers':['Jesse','Jodie']}");
assertEquals(Arrays.asList(new Person("Jesse", -1), new Person("Jodie", -1)), truck.passengers);
}
@ -114,36 +114,36 @@ public final class StreamingTypeAdaptersTest extends TestCase {
Map<String, Double> map = new LinkedHashMap<String, Double>();
map.put("a", 5.0);
map.put("b", 10.0);
assertEquals("{'a':5.0,'b':10.0}", mapAdapter.toJson(map).replace('"', '\''));
assertEquals("{'a':5.0,'b':10.0}", toJson(mapAdapter, map).replace('"', '\''));
}
public void testDeserializeMap() throws IOException {
Map<String, Double> map = new LinkedHashMap<String, Double>();
map.put("a", 5.0);
map.put("b", 10.0);
assertEquals(map, mapAdapter.fromJson("{'a':5.0,'b':10.0}"));
assertEquals(map, fromJson(mapAdapter, "{'a':5.0,'b':10.0}"));
}
public void testSerialize1dArray() throws IOException {
TypeAdapter<double[]> arrayAdapter = miniGson.getAdapter(new TypeToken<double[]>() {});
assertEquals("[1.0,2.0,3.0]", arrayAdapter.toJson(new double[]{1.0, 2.0, 3.0}));
assertEquals("[1.0,2.0,3.0]", toJson(arrayAdapter, new double[]{1.0, 2.0, 3.0}));
}
public void testDeserialize1dArray() throws IOException {
TypeAdapter<double[]> arrayAdapter = miniGson.getAdapter(new TypeToken<double[]>() {});
double[] array = arrayAdapter.fromJson("[1.0,2.0,3.0]");
double[] array = fromJson(arrayAdapter, "[1.0,2.0,3.0]");
assertTrue(Arrays.toString(array), Arrays.equals(new double[]{1.0, 2.0, 3.0}, array));
}
public void testSerialize2dArray() throws IOException {
TypeAdapter<double[][]> arrayAdapter = miniGson.getAdapter(new TypeToken<double[][]>() {});
double[][] array = { {1.0, 2.0 }, { 3.0 } };
assertEquals("[[1.0,2.0],[3.0]]", arrayAdapter.toJson(array));
assertEquals("[[1.0,2.0],[3.0]]", toJson(arrayAdapter, array));
}
public void testDeserialize2dArray() throws IOException {
TypeAdapter<double[][]> arrayAdapter = miniGson.getAdapter(new TypeToken<double[][]>() {});
double[][] array = arrayAdapter.fromJson("[[1.0,2.0],[3.0]]");
double[][] array = fromJson(arrayAdapter, "[[1.0,2.0],[3.0]]");
double[][] expected = { {1.0, 2.0 }, { 3.0 } };
assertTrue(Arrays.toString(array), Arrays.deepEquals(expected, array));
}
@ -191,7 +191,7 @@ public final class StreamingTypeAdaptersTest extends TestCase {
assertEquals("{'label':'root',"
+ "'left':{'label':'left','left':null,'right':null},"
+ "'right':{'label':'right','left':null,'right':null}}",
nodeAdapter.toJson(root).replace('"', '\''));
toJson(nodeAdapter, root).replace('"', '\''));
}
static class Truck {
@ -207,8 +207,6 @@ public final class StreamingTypeAdaptersTest extends TestCase {
this.age = age;
}
public Person() {} // TODO: use Joel's constructor code so we don't need this
@Override public boolean equals(Object o) {
return o instanceof Person
&& ((Person) o).name.equals(name)
@ -226,6 +224,20 @@ public final class StreamingTypeAdaptersTest extends TestCase {
Node(String label) {
this.label = label;
}
public Node() {} // TODO: use Joel's constructor code so we don't need this
}
// TODO: remove this when TypeAdapter.toJson() is public
private static <T> String toJson(TypeAdapter<T> typeAdapter, T value) throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter writer = new JsonWriter(stringWriter);
typeAdapter.write(writer, value);
return stringWriter.toString();
}
// TODO: remove this when TypeAdapter.fromJson() is public
private <T> T fromJson(TypeAdapter<T> typeAdapter, String json) throws IOException {
JsonReader reader = new JsonReader(new StringReader(json));
reader.setLenient(true); // TODO: non-lenient?
return typeAdapter.read(reader);
}
}