想象一下,我们有以下两个类:
public class Test {
private String element1;
private SubTest subTest;
}
public class SubTest {
private String element2;
}
如果我从Test
类创建json,我将有下一个字符串:
{element1:null,subTest:{element2:null}}
但我需要结果json这个观点:
{element1:null,subTest_element2:null}
我知道我可以通过创建一个适配器来实现这一点,我可以根据需要实现序列化方法,但我需要其他东西,例如注释,我将放在private SubTest subTest;
下
有人可以帮我吗?
答案 0 :(得分:2)
Gson 2.2的新TypeAdapterFactory接口为您提供了检查传入类型注释的钩子,并根据这些注释定义了类型适配器。这是一个查找带注释的字段JsonInlined
的完整示例。如果找到,则类型适配器将外部对象序列化为内部对象。
@Retention(RetentionPolicy.RUNTIME)
@interface JsonInlined {}
static class InlinedFieldFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
Class<? super T> rawType = type.getRawType();
Field field = getJsonInlinedField(rawType);
if (field == null) {
return null; // this factory doesn't know how to adapt this type
}
field.setAccessible(true);
TypeAdapter<?> delegate = gson.getAdapter(field.getType());
@SuppressWarnings("unchecked") // this creates a type adapter handles for instances of 'T'
TypeAdapter<T> fieldAdapter = (TypeAdapter<T>) newAdapter(rawType, field, delegate);
return fieldAdapter;
}
private Field getJsonInlinedField(Class<?> c) {
for (Field field : c.getDeclaredFields()) {
if (field.isAnnotationPresent(JsonInlined.class)) {
return field;
}
}
return null;
}
static <F> TypeAdapter<Object> newAdapter(final Class<?> c,
final Field field, final TypeAdapter<F> fieldAdapter) {
return new TypeAdapter<Object>() {
@Override public void write(JsonWriter out, Object value) throws IOException {
try {
if (value != null) {
@SuppressWarnings("unchecked") // we define 'F' by the type of field
F fieldValue = (F) field.get(value);
fieldAdapter.write(out, fieldValue);
} else {
out.nullValue();
}
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
}
@Override public Object read(JsonReader in) throws IOException {
try {
if (in.peek() == JsonToken.NULL) {
return null;
} else {
Object instance = c.newInstance();
field.set(instance, fieldAdapter.read(in));
return instance;
}
} catch (InstantiationException e) {
throw new AssertionError(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
}
};
}
}
我不打算解释整个实施;对TypeAdapter和TypeAdapterFactory javadocs中的移动部分有一个不错的描述。
最重要的是要记住,您可以使用其他类型适配器编写类型的适配器。工厂API强制您预先完成所有的反射。这有助于更早地捕获错误,并且还有助于您的代码更有效地运行。