gpt4 book ai didi

java - 向 GSON 注册多个适配器不起作用

转载 作者:太空狗 更新时间:2023-10-29 22:47:46 25 4
gpt4 key购买 nike

我在使用 GsonBuilder 注册多个类型适配器时遇到问题。似乎只有一个会开火,而从不考虑第二个。如果我单独对每一个进行处理,它似乎工作正常。但我需要他们与两者一起工作,似乎我做错了什么。另外,我目前正在使用 GSON v2.2.4。

Zip 对象简单形式:

public class Zip {

private String zipCode;
private String city;
private String state;

public Zip(){}
}

ZipSerializer:

public class ZipSerializer implements JsonSerializer<Zip>{

@Override
public JsonElement serialize(Zip obj, Type type, JsonSerializationContext jsc) {
Gson gson = new Gson();
JsonObject jObj = (JsonObject)gson.toJsonTree(obj);
jObj.remove("state");
return jObj;
}

}

JsonResponse 对象简单形式:

public class JsonResponse {

private String jsonrpc = "2.0";
private Object result = null;
private String id = null;

public JsonResponse(){}

}

JsonResponseSerializer:

public class JsonResponseSerializer implements JsonSerializer<JsonResponse> {

@Override
public JsonElement serialize(JsonResponse obj, Type type, JsonSerializationContext jsc) {
Gson gson = new Gson();
JsonObject jObj = (JsonObject)gson.toJsonTree(obj);
jObj.remove("id");

return jObj;
}

}

测试示例:

public class Test {

public static void main(String[] args) {
Zip zip = new Zip();
zip.setCity("testcity");
zip.setState("OH");
zip.setZipCode("12345");

JsonResponse resp = new JsonResponse();
resp.setId("1");
resp.setResult(zip);
resp.setJsonrpc("2.0");

Gson gson1 = new GsonBuilder()
.registerTypeAdapter(JsonResponse.class, new JsonResponseSerializer())
.registerTypeAdapter(Zip.class, new ZipSerializer())
.setPrettyPrinting()
.create();


String json = gson1.toJson(resp);
System.out.println(json);

}

}

输出:

{
"jsonrpc": "2.0",
"result": {
"zipCode": "12345",
"city": "testcity",
"state": "OH"
}
}

预期输出:(注意 ZipSerializer 没有启动)

{
"jsonrpc": "2.0",
"result": {
"zipCode": "12345",
"city": "testcity"
}
}

我为此简化了测试用例。我知道我可以在此示例中使用 exclusionStrategy 来获得结果,但真正的问题要复杂得多,这是我描述和复制问题的最佳方式。

谢谢

<---------------------------- 解决方案 -------------- -------------->

我设法阅读了 Gson custom seralizer for one variable (of many) in an object using TypeAdapter这对我帮助很大。

我创建了一个基本的 customTypeAdapterFactory,然后为每个需要特殊序列化的类扩展它。

自定义类型适配器工厂

public abstract class CustomizedTypeAdapterFactory<C> implements TypeAdapterFactory {

private final Class<C> customizedClass;

public CustomizedTypeAdapterFactory(Class<C> customizedClass) {
this.customizedClass = customizedClass;
}

@SuppressWarnings("unchecked") // we use a runtime check to guarantee that 'C' and 'T' are equal
public final <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
return type.getRawType() == customizedClass
? (TypeAdapter<T>) customizeMyClassAdapter(gson, (TypeToken<C>) type)
: null;
}

private TypeAdapter<C> customizeMyClassAdapter(Gson gson, TypeToken<C> type) {
final TypeAdapter<C> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);

return new TypeAdapter<C>() {

@Override public void write(JsonWriter out, C value) throws IOException {
JsonElement tree = delegate.toJsonTree(value);
beforeWrite(value, tree);
elementAdapter.write(out, tree);
}


@Override public C read(JsonReader in) throws IOException {
JsonElement tree = elementAdapter.read(in);
afterRead(tree);
return delegate.fromJsonTree(tree);
}
};
}

/**
* Override this to muck with {@code toSerialize} before it is written to
* the outgoing JSON stream.
*/
protected void beforeWrite(C source, JsonElement toSerialize) {
}

/**
* Override this to muck with {@code deserialized} before it parsed into
* the application type.
*/
protected void afterRead(JsonElement deserialized) {
}
}

ZipTypeAdapterFactory(用 JsonResponseTypeAdapterFactory 做的)

public class ZipTypeAdapterFactory  extends CustomizedTypeAdapterFactory<Zip> {

ZipTypeAdapterFactory() {
super(Zip.class);
}

@Override
protected void beforeWrite(Zip source, JsonElement toSerialize) {
JsonObject obj = (JsonObject) toSerialize;
obj.remove("state");
}

}

测试代码:

Gson gson1 = new GsonBuilder()
.registerTypeAdapterFactory(new JsonResponseTypeAdapterFactory())
.registerTypeAdapterFactory(new ZipTypeAdapterFactory())
.setPrettyPrinting()
.create();


String json = gson1.toJson(resp);
System.out.println(json);

谢谢大家的帮助。

最佳答案

问题出在您的 JsonResponseSerializer 中。你创建了一个新的 Gson 实例,然后在这个新实例上 ZipSerializer 没有被注册。这就是为什么您的第二个序列化程序永远不会被调用的原因。

如果要实现委托(delegate)和复杂的序列化,看TypeAdapterFactory

如您所说,如果您只是想从序列化中过滤字段,请定义一个 ExclusionStrategy

关于java - 向 GSON 注册多个适配器不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17984139/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com