我知道Gson没有类似的功能,但有没有办法像public class Person {
public int age;
public Name name;
}
public class Name {
public String first;
public String last;
}
一样添加对Json字段展开的支持?
目标是允许类似以下的结构:
{
"age" : 18,
"first" : "Joey",
"last" : "Sixpack"
}
被(de)序列化为:
{
"age" : 18,
"name" : {
"first" : "Joey",
"last" : "Sixpack"
}
}
而不是:
{{1}}
我知道它可能变得相当复杂,所以我不是在寻找一个完整的解决方案,只是一些高级指南,如果这是可行的。
答案 0 :(得分:2)
我做了一个支持这个的解串器的粗略实现。它是完全通用的(类型无关的),但也昂贵且易碎,我不会将它用于任何严重的事情。我发帖只是为了向别人展示我得到的东西,如果他们最终需要做类似的事情。
public class UnwrappingDeserializer implements JsonDeserializer<Object> {
//This Gson needs to be identical to the global one, sans this deserializer to prevent infinite recursion
private Gson delegate;
public UnwrappingDeserializer(Gson delegate) {
this.delegate = delegate;
}
@Override
public Object deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
Object def = delegate.fromJson(json, type); //Gson doesn't care about unknown fields
Class raw = GenericTypeReflector.erase(type);
Set<Field> unwrappedFields = ClassUtils.getAnnotatedFields(raw, GsonUnwrap.class);
for (Field field : unwrappedFields) {
AnnotatedType fieldType = GenericTypeReflector.getExactFieldType(field, type);
field.setAccessible(true);
try {
Object fieldValue = deserialize(json, fieldType.getType(), context);
field.set(def, fieldValue);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
return def;
}
}
然后可以通过new GsonBuilder().registerTypeHierarchyAdapter(Object.class, new UnwrappingDeserializer(new Gson())).create()
在全球注册,也可以通过registerTypeAdapter
注册特定类型。
备注:强>
GsonUnwrap
,将结果缓存在并发映射中,并且只在需要时才执行此过程。否则它应该立即返回def
GenericTypeReflector
来自GeAnTyRef ClassUtils#getAnnotatedFields
是我自己的实现,但它没有做任何特别的事情 - 它只是递归地为类层次结构收集声明的字段(通过Class#getDeclaredFields
)GsonUnwrap
只是一个简单的自定义注释我认为也可以为序列化做类似的事情。从Derlin's answer链接的示例可以作为起点。
答案 1 :(得分:1)
目前,没有简单的方法可以做到这一点。无论如何,这里有一些指示/替代方法使其发挥作用。
GsonFire :GsonFire实现了Gson缺少的一些有用功能。虽然它还没有提供自动包装/展开,但它可能是创建自定义逻辑的一个很好的起点。
如果您只需要序列化,则可以在first
中为last
和Person
添加getter,并使用@ExposeMethodResult
对其进行序列化。不幸的是,不支持setter(参见Is possible to use setters when Gson deserializes a JSON?)。
支持序列化的另一种方法是遵循How to move fields to parent object的建议。
自定义TypeAdapters :支持序列化和反序列化的唯一方法是创建自定义TypeAdapter
。这不是通用的,但它适合您的用例。
线程Serialize Nested Object as Attributes已经为您提供了示例,因此我不会在此重复这些内容。