让我们从共享工作和可复制的代码开始(需要google gson包):
package mypackage;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
public final class ALL {
static final Gson GSON = new GsonBuilder().registerTypeAdapterFactory(new Factory()).create();
/////////////////////////////////////////////////////////////////////
@Target( { METHOD, FIELD, ANNOTATION_TYPE, TYPE })
@Retention(RUNTIME)
public @interface Serialize {}
/////////////////////////////////////////////////////////////////////
public static void main(String[] args) {
Test test = new Test();
String json = GSON.toJson(test);
System.out.println(json);
}
/////////////////////////////////////////////////////////////////////
public static final class Test {
@Serialize
String abc = "def";
}
/////////////////////////////////////////////////////////////////////
public static final class Factory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
Serialize annotation = type.getRawType().getAnnotation(Serialize.class);
boolean annotationPresent = type.getRawType().isAnnotationPresent(Serialize.class);
Annotation[] annotations = type.getRawType().getAnnotations();
if (annotationPresent) {
System.out.println("11111111111111");
}
if (annotation != null) {
return new Adapter<>();
}
return gson.getDelegateAdapter(this, type);
}
}
/////////////////////////////////////////////////////////////////////
public static final class Adapter<T> extends TypeAdapter<T> {
private static final java.util.Base64.Encoder ENCODER = java.util.Base64.getEncoder();
private static final java.util.Base64.Decoder DECODER = java.util.Base64.getDecoder();
@Override
public T read(JsonReader in) throws IOException {
in.beginObject();
String a = in.nextString();
in.endObject();
try {
return deserialize( DECODER.decode(a) );
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
@Override
public void write(JsonWriter out, T value) throws IOException {
out.value( encode(serialize(value)) );
}
private String encode(byte[] serialize) {
return ENCODER.encodeToString( serialize );
}
private byte[] serialize(T value) throws IOException {
try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream os = new ObjectOutputStream(out); ) {
os.writeObject(value);
return out.toByteArray();
}
}
private T deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
try (ByteArrayInputStream in = new ByteArrayInputStream(bytes); ObjectInputStream is = new ObjectInputStream(in); ) {
return (T) is.readObject();
}
}
}
}
如果我们看看 Test
类,目标是在注解 @Serialize
存在。在本例中,我们以字符串形式输出字节。当我们读回这个时,我们想反序列化它。
理解这个目标的另一种方法是考虑使用一个注解来加密一个值,然后在readback上解密它。
这应该是可能的,不是吗?
我知道我可以基于字段类型注册typeadapters,但是,我希望能够使用注解来声明意图。
没有 Package 类。您可以创建自定义jsonserializer,但这需要注册。
在上面的例子中 type.getRawType().getAnnotation(Serialize.class);
总是返回null和 Annotation[] annotations = type.getRawType().getAnnotations()
总是空的,所以无法检测使用工厂。
不确定如何动态检测注解。
你知道吗?
1条答案
按热度按时间avkwfej41#
使用@jsonadapter怎么样?无论如何,您需要知道如何进行解密,并且需要实现每个类型的tha。例如,对于本例中的字符串:
用法:
问题是,据我所知,gson没有提供任何直接的方法来创建一些自己的字段处理器,使用户可以读取字段/类成员注解。
换句话说,您需要在反序列化/序列化期间访问该字段,这似乎不可能以简单的方式实现。
所以才有这个
@JsonAdapter
.如果有兴趣从github学习更多克隆源代码,请检查:
不幸的是
final
. 有一个名为createBoundField
(我认为这就是@JsonAdapter
对于字段),路径和重写该逻辑并不是那么简单。对于类,似乎有与您的解决方案非常相似的解决方案:
上述两项均已列入
TypeAdapterFactories
当一个新的Gson
已创建。