Mam problem z rejestrowaniem wielu kart typu Adapters za pomocą mojego GsonBuilder. Wygląda na to, że tylko jeden odpali i nigdy nie bierze pod uwagę drugiego. Jeśli robię to z każdym z osobna, wydaje mi się, że działa dobrze. Ale potrzebuję ich do pracy z obydwoma i wydaje mi się, że robię coś złego. Również obecnie używam GSON v2.2.4.Rejestracja wielu adapterów za pomocą narzędzia GSON nie działa.
pocztowy obiektu prostą postać:
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 obiektu prostą postać:
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;
}
}
Przykład testowy:
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);
}
}
wyjściowa:
{
"jsonrpc": "2.0",
"result": {
"zipCode": "12345",
"city": "testcity",
"state": "OH"
}
}
oczekiwany wynik: (Wskazówka ZipSerializer nie wystrzelić)
{
"jsonrpc": "2.0",
"result": {
"zipCode": "12345",
"city": "testcity"
}
}
I simpled dół przypadek testowy dla tego produktu. Wiem, że mogę użyć exclusionStrategy w tym przykładzie, aby osiągnąć wyniki, ale prawdziwy problem jest znacznie bardziej złożony i był to najlepszy sposób, aby przedstawić i powtórzyć mój problem.
Dzięki
< ---------------------------- ROZWIĄZANIE ----------- -------------------->
Udało mi się przeczytać Gson custom seralizer for one variable (of many) in an object using TypeAdapter i bardzo mi to pomogło.
Utworzono podstawowy customTypeAdapterFactory, a następnie rozszerzono go dla każdej klasy wymagającej specjalnej serializacji.
CustomizedTypeAdapterFactory
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 (czy to z 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");
}
}
Code Test:
Gson gson1 = new GsonBuilder()
.registerTypeAdapterFactory(new JsonResponseTypeAdapterFactory())
.registerTypeAdapterFactory(new ZipTypeAdapterFactory())
.setPrettyPrinting()
.create();
String json = gson1.toJson(resp);
System.out.println(json);
Dziękuję wszystkim za pomoc.
Dzięki za wyjaśnienie. Musiałem źle zrozumieć sposób działania JsonSerializer. Tak jak powiedziałem, zrobiłem mój przykład prawdopodobnie podstawowy przykład, że mogłem replikować problem i gdzie faktycznie jestem w strategiach wykluczenia prawdopodobnie nie jest to najlepszy sposób. Zajrzę do TypeAdapterFactory, która jest dla mnie nowością, z niewielkim zrozumieniem. – dayv2005
Możesz obejrzeć tutaj, jeśli chcesz zobaczyć przykładowy kod z delegacją: http://stackoverflow.com/questions/17909602/deserialize-to-type-at-runtime/17925280#17925280. – PomPom
i zamknij wpis, jeśli masz odpowiedź;) – PomPom