/* * Copyright (C) 2011 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; import com.google.gson.internal.bind.JsonTreeReader; import com.google.gson.internal.bind.JsonTreeWriter; 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. * *
{@code * * public class PointAdapter extends TypeAdapter* With this type adapter installed, Gson will convert {@code Points} to JSON as * strings like {@code "5,8"} rather than objects like {@code {"x":5,"y":8}}. In * this case the type adapter binds a rich Java class to a compact JSON value. * *{ * public Point read(JsonReader reader) throws IOException { * if (reader.peek() == JsonToken.NULL) { * reader.nextNull(); * return null; * } * String xy = reader.nextString(); * String[] parts = xy.split(","); * int x = Integer.parseInt(parts[0]); * int y = Integer.parseInt(parts[1]); * return new Point(x, y); * } * public void write(JsonWriter writer, Point value) throws IOException { * if (value == null) { * writer.nullValue(); * return; * } * String xy = value.getX() + "," + value.getY(); * writer.value(xy); * } * }}
The {@link #read(JsonReader) read()} method must read exactly one value
* and {@link #write(JsonWriter,Object) write()} must write exactly one value.
* For primitive types this is means readers should make exactly one call to
* {@code nextBoolean()}, {@code nextDouble()}, {@code nextInt()}, {@code
* nextLong()}, {@code nextString()} or {@code nextNull()}. Writers should make
* exactly one call to one of value()
or nullValue()
.
* For arrays, type adapters should start with a call to {@code beginArray()},
* convert all elements, and finish with a call to {@code endArray()}. For
* objects, they should start with {@code beginObject()}, convert the object,
* and finish with {@code endObject()}. Failing to convert a value or converting
* too many values may cause the application to crash.
*
*
Type adapters should be prepared to read null from the stream and write it * to the stream. Alternatively, they should use {@link #nullSafe()} method while * registering the type adapter with Gson. If your {@code Gson} instance * has been configured to {@link GsonBuilder#serializeNulls()}, these nulls will be * written to the final document. Otherwise the value (and the corresponding name * when writing to a JSON object) will be omitted automatically. In either case * your type adapter must handle null. * *
Type adapters should be stateless and thread-safe, otherwise the thread-safety * guarantees of {@link Gson} might not apply. * *
To use a custom type adapter with Gson, you must register it with a * {@link GsonBuilder}:
{@code * * GsonBuilder builder = new GsonBuilder(); * builder.registerTypeAdapter(Point.class, new PointAdapter()); * // if PointAdapter didn't check for nulls in its read/write methods, you should instead use * // builder.registerTypeAdapter(Point.class, new PointAdapter().nullSafe()); * ... * Gson gson = builder.create(); * }* * @since 2.1 */ // non-Javadoc: // //
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:
{@code // // String json = "{'origin':'0,0','points':['1,2','3,4']}"; // TypeAdapter// And an example for serialization:graphAdapter = gson.getAdapter(Graph.class); // Graph graph = graphAdapter.fromJson(json); // }
{@code // // Graph graph = new Graph(...); // TypeAdapter// //graphAdapter = gson.getAdapter(Graph.class); // String json = graphAdapter.toJson(graph); // }
Type adapters are type-specific. For example, a {@code
// TypeAdapter No exception is thrown if the JSON data has multiple top-level JSON elements,
* or if there is trailing data.
*
* @return the converted Java object. May be null.
* @since 2.2
*/
public final T fromJson(Reader in) throws IOException {
JsonReader reader = new JsonReader(in);
return read(reader);
}
/**
* Converts the JSON document in {@code json} to a Java object. Unlike Gson's
* similar {@link Gson#fromJson(String, Class) fromJson} method, this read is
* strict. Create a {@link JsonReader#setLenient(boolean) lenient} {@code
* JsonReader} and call {@link #read(JsonReader)} for lenient reading.
*
* No exception is thrown if the JSON data has multiple top-level JSON elements,
* or if there is trailing data.
*
* @return the converted Java object. May be null.
* @since 2.2
*/
public final T fromJson(String json) throws IOException {
return fromJson(new StringReader(json));
}
/**
* Converts {@code jsonTree} to a Java object.
*
* @param jsonTree the JSON element to convert. May be {@link JsonNull}.
* @return the converted Java object. May be null.
* @throws JsonIOException wrapping {@code IOException}s thrown by {@link #read(JsonReader)}
* @since 2.2
*/
public final T fromJsonTree(JsonElement jsonTree) {
try {
JsonReader jsonReader = new JsonTreeReader(jsonTree);
return read(jsonReader);
} catch (IOException e) {
throw new JsonIOException(e);
}
}
}
* {@code
*
* Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
* new TypeAdapter
* You can avoid this boilerplate handling of nulls by wrapping your type adapter with
* this method. Here is how we will rewrite the above example:
* {@code
*
* Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
* new TypeAdapter
* Note that we didn't need to check for nulls in our type adapter after we used nullSafe.
*/
public final TypeAdapter