diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index 6995b0a2..6be1e41a 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -180,6 +180,53 @@ public final class Gson { return new DisjunctionExclusionStrategy(strategies); } + /** + * 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. + * This method uses {@link Class#getClass()} to get the type for the specified object, but 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, + * 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 Writer}, use {@link #toJson(Object, Appendable)} instead. + * + * @param src the object for which Json representation is to be created setting for Gson + * @return Json representation of {@code src}. + * @since 1.4 + */ + public JsonElement toJsonTree(Object src) { + if (src == null) { + return JsonNull.createJsonNull(); + } + return toJsonTree(src, src.getClass()); + } + + /** + * 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 + * specified object is a generic type. For non-generic objects, use {@link #toJson(Object)} + * instead. If you want to write out the object to a {@link Appendable}, + * use {@link #toJson(Object, Type, Appendable)} instead. + * + * @param src the object for which JSON representation is to be created + * @param typeOfSrc The specific genericized type of src. You can obtain + * this type by using the {@link com.google.gson.reflect.TypeToken} class. For example, + * to get the type for {@code Collection}, you should use: + *
+   * Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
+   * 
+ * @return Json representation of {@code src} + * @since 1.4 + */ + public JsonElement toJsonTree(Object src, Type typeOfSrc) { + if (src == null) { + return JsonNull.createJsonNull(); + } + JsonSerializationContext context = new JsonSerializationContextDefault( + createDefaultObjectNavigatorFactory(), serializeNulls, serializers); + return context.serialize(src, typeOfSrc); + } + /** * This method serializes the specified object into its equivalent Json representation. * This method should be used when the specified object is not a generic type. This method uses @@ -220,7 +267,7 @@ public final class Gson { toJson(src, typeOfSrc, writer); return writer.toString(); } - + /** * This method serializes the specified object into its equivalent Json representation. * This method should be used when the specified object is not a generic type. This method uses @@ -263,21 +310,11 @@ public final class Gson { */ public void toJson(Object src, Type typeOfSrc, Appendable writer) { try { - if (src != null) { - JsonSerializationContext context = new JsonSerializationContextDefault( - createDefaultObjectNavigatorFactory(), serializeNulls, serializers); - JsonElement jsonElement = context.serialize(src, typeOfSrc); - - if (generateNonExecutableJson) { - writer.append(JSON_NON_EXECUTABLE_PREFIX); - } - //TODO(Joel): instead of navigating the "JsonElement" inside the formatter, do it here. - formatter.format(jsonElement, writer, serializeNulls); - } else { - if (serializeNulls) { - writeOutNullString(writer); - } + if (generateNonExecutableJson) { + writer.append(JSON_NON_EXECUTABLE_PREFIX); } + JsonElement jsonElement = toJsonTree(src, typeOfSrc); + formatter.format(jsonElement, writer, serializeNulls); } catch (IOException ioe) { throw new RuntimeException(ioe); } diff --git a/gson/src/test/java/com/google/gson/functional/JsonTreeTest.java b/gson/src/test/java/com/google/gson/functional/JsonTreeTest.java new file mode 100644 index 00000000..f40bd2b6 --- /dev/null +++ b/gson/src/test/java/com/google/gson/functional/JsonTreeTest.java @@ -0,0 +1,76 @@ +package com.google.gson.functional; + +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +import junit.framework.TestCase; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.google.gson.common.TestTypes.BagOfPrimitives; + +/** + * Functional tests for {@link Gson#toJsonTree(Object) and + * {@link Gson#toJsonTree(Object, java.lang.reflect.Type) + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public class JsonTreeTest extends TestCase { + private Gson gson; + + @Override + protected void setUp() throws Exception { + super.setUp(); + gson = new Gson(); + } + + public void testToJsonTree() { + BagOfPrimitives bag = new BagOfPrimitives(10L, 5, false, "foo"); + JsonElement json = gson.toJsonTree(bag); + assertTrue(json.isJsonObject()); + JsonObject obj = json.getAsJsonObject(); + Set> children = obj.entrySet(); + assertEquals(4, children.size()); + assertContains(obj, new JsonPrimitive(10L)); + assertContains(obj, new JsonPrimitive(5)); + assertContains(obj, new JsonPrimitive(false)); + assertContains(obj, new JsonPrimitive("foo")); + } + + public void testToJsonTreeObjectType() { + SubTypeOfBagOfPrimitives bag = new SubTypeOfBagOfPrimitives(10L, 5, false, "foo", 1.4F); + JsonElement json = gson.toJsonTree(bag, BagOfPrimitives.class); + assertTrue(json.isJsonObject()); + JsonObject obj = json.getAsJsonObject(); + Set> children = obj.entrySet(); + assertEquals(4, children.size()); + assertContains(obj, new JsonPrimitive(10L)); + assertContains(obj, new JsonPrimitive(5)); + assertContains(obj, new JsonPrimitive(false)); + assertContains(obj, new JsonPrimitive("foo")); + } + + private void assertContains(JsonObject json, JsonPrimitive child) { + for (Map.Entry entry : json.entrySet()) { + JsonElement node = entry.getValue(); + if (node.isJsonPrimitive()) { + if (node.getAsJsonPrimitive().equals(child)) { + return; + } + } + } + fail(); + } + + private static class SubTypeOfBagOfPrimitives extends BagOfPrimitives { + float f = 1.2F; + public SubTypeOfBagOfPrimitives(long l, int i, boolean b, String string, float f) { + super(l, i, b, string); + this.f = f; + } + } +}