Created an alpha package that holds experimental feature.
Added support for JsonPostDeserializer that allows you to invoke postDeserialize methods on an Gson deserialized object.
This commit is contained in:
parent
14f16e2d0c
commit
c25278b4d6
@ -33,8 +33,11 @@ import java.util.Map;
|
||||
|
||||
import com.google.gson.internal.ConstructorConstructor;
|
||||
import com.google.gson.internal.Excluder;
|
||||
import com.google.gson.internal.ObjectConstructor;
|
||||
import com.google.gson.internal.Primitives;
|
||||
import com.google.gson.internal.Streams;
|
||||
import com.google.gson.internal.alpha.Intercept;
|
||||
import com.google.gson.internal.alpha.JsonPostDeserializer;
|
||||
import com.google.gson.internal.bind.ArrayTypeAdapter;
|
||||
import com.google.gson.internal.bind.CollectionTypeAdapterFactory;
|
||||
import com.google.gson.internal.bind.DateTypeAdapter;
|
||||
@ -791,8 +794,11 @@ public final class Gson {
|
||||
try {
|
||||
reader.peek();
|
||||
isEmpty = false;
|
||||
TypeAdapter<T> typeAdapter = (TypeAdapter<T>) getAdapter(TypeToken.get(typeOfT));
|
||||
return typeAdapter.read(reader);
|
||||
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
|
||||
TypeAdapter<T> typeAdapter = (TypeAdapter<T>) getAdapter(typeToken);
|
||||
T object = typeAdapter.read(reader);
|
||||
invokeInterceptorIfNeeded(object, typeToken);
|
||||
return object;
|
||||
} catch (EOFException e) {
|
||||
/*
|
||||
* For compatibility with JSON 1.5 and earlier, we return null for empty
|
||||
@ -884,6 +890,20 @@ public final class Gson {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private <T> void invokeInterceptorIfNeeded(T object, TypeToken<T> type) {
|
||||
Class<? super T> clazz = type.getRawType();
|
||||
Intercept interceptor = clazz.getAnnotation(Intercept.class);
|
||||
if (interceptor == null) return;
|
||||
// TODO: We don't need to construct an instance of postDeserializer every time. we can
|
||||
// create it once and cache it.
|
||||
Class<? extends JsonPostDeserializer> postDeserializerClass = interceptor.postDeserialize();
|
||||
ObjectConstructor<? extends JsonPostDeserializer> objectConstructor =
|
||||
constructorConstructor.get(TypeToken.get(postDeserializerClass));
|
||||
JsonPostDeserializer<T> postDeserializer = objectConstructor.construct();
|
||||
postDeserializer.postDeserialize(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("{")
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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.internal.alpha;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
/**
|
||||
* Use this annotation to indicate various interceptors for class instances after
|
||||
* they have been processed by Gson. For example, you can use it to validate an instance
|
||||
* after it has been deserialized from Json.
|
||||
* Here is an example of how this annotation is used:
|
||||
* <p>Here is an example of how this annotation is used:
|
||||
* <p><pre>
|
||||
* @Intercept(postDeserialize=UserValidator.class)
|
||||
* public class User {
|
||||
* String name;
|
||||
* String password;
|
||||
* String emailAddress;
|
||||
* }
|
||||
*
|
||||
* public class UserValidator implements JsonPostDeserializer<User> {
|
||||
* public void postDeserialize(User user) {
|
||||
* // Do some checks on user
|
||||
* if (user.name == null || user.password == null) {
|
||||
* throw new JsonParseException("name and password are required fields.");
|
||||
* }
|
||||
* if (user.emailAddress == null) {
|
||||
* emailAddress = "unknown"; // assign a default value.
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre></p>
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface Intercept {
|
||||
|
||||
/**
|
||||
* Specify the class that provides the methods that should be invoked after an instance
|
||||
* has been deserialized.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Class<? extends JsonPostDeserializer> postDeserialize();
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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.internal.alpha;
|
||||
|
||||
import com.google.gson.InstanceCreator;
|
||||
|
||||
/**
|
||||
* This interface is implemented by a class that wishes to inspect or modify an object
|
||||
* after it has been deserialized. You must define a no-args constructor or register an
|
||||
* {@link InstanceCreator} for such a class.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
*/
|
||||
public interface JsonPostDeserializer<T> {
|
||||
|
||||
/**
|
||||
* This method is called by Gson after the object has been deserialized from Json.
|
||||
*/
|
||||
public void postDeserialize(T object);
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* This package provides experimental Gson features that are very likely to change from
|
||||
* release to release. Backwards compatibility will almost certainly be broken in a future
|
||||
* release by either changing the package name (when the feature moves to main Gson) or when
|
||||
* we decide that the feature isn't worth adding.
|
||||
*
|
||||
* @author Inderjeet Singh, Joel Leitch, Jesse Wilson
|
||||
*/
|
||||
package com.google.gson.internal.alpha;
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2012 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.functional;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.internal.alpha.Intercept;
|
||||
import com.google.gson.internal.alpha.JsonPostDeserializer;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link Intercept} and {@link JsonPostDeserializer}.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
*/
|
||||
public final class InterceptorTest extends TestCase {
|
||||
|
||||
private Gson gson;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.gson = new Gson();
|
||||
}
|
||||
|
||||
public void testPostDeserialize() {
|
||||
MyObject target = gson.fromJson("{}", MyObject.class);
|
||||
assertEquals(MyObject.DEFAULT_VALUE, target.value);
|
||||
assertEquals(MyObject.DEFAULT_MESSAGE, target.message);
|
||||
}
|
||||
|
||||
@Intercept(postDeserialize = MyObjectInterceptor.class)
|
||||
private static final class MyObject {
|
||||
static final int DEFAULT_VALUE = 10;
|
||||
static final String DEFAULT_MESSAGE = "hello";
|
||||
|
||||
int value = 0;
|
||||
String message = null;
|
||||
}
|
||||
|
||||
private static final class MyObjectInterceptor implements JsonPostDeserializer<MyObject> {
|
||||
public void postDeserialize(MyObject o) {
|
||||
if (o.value == 0) {
|
||||
o.value = MyObject.DEFAULT_VALUE;
|
||||
}
|
||||
if (o.message == null) {
|
||||
o.message = MyObject.DEFAULT_MESSAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user