From 6f59bc3bfea8ccdff1bfd0640351241ccf4100ff Mon Sep 17 00:00:00 2001 From: Joel Leitch Date: Mon, 1 Dec 2008 00:10:04 +0000 Subject: [PATCH] Added "Until" type version. This new annotation allows you to remove members from the JSON output beginning at a certain version number. This new annotation work in conjunction with the "@Since" annotation. --- .../google/gson/VersionExclusionStrategy.java | 28 +++++++-- .../com/google/gson/annotations/Until.java | 63 +++++++++++++++++++ .../gson/functional/VersioningTest.java | 14 ++++- 3 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 gson/src/main/java/com/google/gson/annotations/Until.java diff --git a/gson/src/main/java/com/google/gson/VersionExclusionStrategy.java b/gson/src/main/java/com/google/gson/VersionExclusionStrategy.java index 58161cc0..60f36ece 100644 --- a/gson/src/main/java/com/google/gson/VersionExclusionStrategy.java +++ b/gson/src/main/java/com/google/gson/VersionExclusionStrategy.java @@ -17,6 +17,7 @@ package com.google.gson; import com.google.gson.annotations.Since; +import com.google.gson.annotations.Until; import java.lang.annotation.Annotation; import java.lang.reflect.Field; @@ -45,11 +46,28 @@ final class VersionExclusionStrategy implements ExclusionStrategy { private boolean isValidVersion(Annotation[] annotations) { for (Annotation annotation : annotations) { - if (annotation instanceof Since) { - double annotationVersion = ((Since) annotation).value(); - if (annotationVersion > version) { - return false; - } + if (!isValidSince(annotation) || !isValidUntil(annotation)) { + return false; + } + } + return true; + } + + private boolean isValidSince(Annotation annotation) { + if (annotation instanceof Since) { + double annotationVersion = ((Since) annotation).value(); + if (annotationVersion > version) { + return false; + } + } + return true; + } + + private boolean isValidUntil(Annotation annotation) { + if (annotation instanceof Until) { + double annotationVersion = ((Until) annotation).value(); + if (annotationVersion <= version) { + return false; } } return true; diff --git a/gson/src/main/java/com/google/gson/annotations/Until.java b/gson/src/main/java/com/google/gson/annotations/Until.java new file mode 100644 index 00000000..bc39d8f6 --- /dev/null +++ b/gson/src/main/java/com/google/gson/annotations/Until.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008 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.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An annotation that indicates the version number until a member or a type should be present. + * Basically, if Gson is created with a version number that exceeds the value stored in the + * {@code Until} annotation then the field will be ignored from the JSON output. This annotation + * is useful to manage versioning of your JSON classes for a web-service. + * + *

+ * This annotation has no effect unless you build {@link com.google.gson.Gson} with a + * {@link com.google.gson.GsonBuilder} and invoke + * {@link com.google.gson.GsonBuilder#setVersion(double)} method. + * + *

Here is an example of how this annotation is meant to be used:

+ *
+ * public class User {
+ *   private String firstName;
+ *   private String lastName;
+ *   @Until(1.1) private String emailAddress;
+ *   @Until(1.1) private String password;
+ * }
+ * 
+ * + *

If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()} + * methods will use all the fields for serialization and deserialization. However, if you created + * Gson with {@code Gson gson = new GsonBuilder().setVersion(1.2).create()} the the + * {@code toJson()} and {@code fromJson()} methods of Gson will exclude the {@code emailAddress} + * and {@code password} fields because the version number passed to the GsonBuilder, {@code 1.2}, + * exceeds the version number set on the {@code Until} annotation for those fields. + * + * @author Joel Leitch + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.TYPE}) +public @interface Until { + + /** + * the value indicating a version number until this member + * or type should be ignored. + */ + double value(); +} diff --git a/gson/src/test/java/com/google/gson/functional/VersioningTest.java b/gson/src/test/java/com/google/gson/functional/VersioningTest.java index f65e22ce..55b44589 100644 --- a/gson/src/test/java/com/google/gson/functional/VersioningTest.java +++ b/gson/src/test/java/com/google/gson/functional/VersioningTest.java @@ -18,6 +18,7 @@ package com.google.gson.functional; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.annotations.Since; +import com.google.gson.annotations.Until; import com.google.gson.common.TestTypes.BagOfPrimitives; import junit.framework.TestCase; @@ -42,6 +43,17 @@ public class VersioningTest extends TestCase { builder = new GsonBuilder(); } + public void testVersionedUntilSerialization() { + Version1 target = new Version1(); + Gson gson = builder.setVersion(1.29).create(); + String json = gson.toJson(target); + assertTrue(json.contains("\"a\":" + A)); + + gson = builder.setVersion(1.3).create(); + json = gson.toJson(target); + assertFalse(json.contains("\"a\":" + A)); + } + public void testVersionedClassesSerialization() { Gson gson = builder.setVersion(1.0).create(); String json1 = gson.toJson(new Version1()); @@ -97,7 +109,7 @@ public class VersioningTest extends TestCase { } private static class Version1 { - int a = A; + @Until(1.3) int a = A; @Since(1.0) int b = B; }