2013-08-01 9 views
13

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.

Odpowiedz

4

Problem jest w Twoim JsonResponseSerializer. Tworzysz nową instancję Gson, a następnie na tej nowej instancji ZipSerializer nie jest zarejestrowana. Dlatego twój drugi serializer nigdy nie jest wywoływany.

Jeśli chcesz uzyskać delegację i złożoną serializację, spójrz na numer TypeAdapterFactory.

Tak jak powiedziałeś, jeśli chcesz po prostu przefiltrować pola z serializacji, zdefiniuj numer ExclusionStrategy.

+0

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

+0

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

+0

i zamknij wpis, jeśli masz odpowiedź;) – PomPom

Powiązane problemy