2011-05-31 15 views
15
public class UserAction { 
    private final UUID uuid; 
    private String userId; 
    /* more fields, setters and getters here */ 

    public UserAction(){ 
     this.uuid = UUID.fromString(new com.eaio.uuid.UUID().toString()); 
    } 

    public UserAction(UUID uuid){ 
     this.uuid = uuid; 
    } 
    @Override 
    public boolean equals(Object obj) { 
     if (obj == null) { 
      return false; 
     } 
     if (getClass() != obj.getClass()) { 
      return false; 
     } 
     final UserAction other = (UserAction) obj; 
     if (this.uuid != other.uuid && (this.uuid == null || !this.uuid.equals(other.uuid))) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 7; 
     hash = 53 * hash + (this.uuid != null ? this.uuid.hashCode() : 0); 
     return hash; 
    } 
} 

Estoy usando Gson para serializar y deserializar esta clase. Como hoy tuve que agregar un UUID final en este objeto. No tengo problemas para serializar. Necesito forzar a gson a usar el constructor public UserAction(UUID uuid) al deserializar. ¿Cómo puedo lograr eso?Fuerza GSON para usar el constructor específico

Respuesta

17

Puede implementar un JsonDeserializer personalizado y registrarlo con GSON.

class UserActionDeserializer implements JsonDeserializer<UserAction> { 
    public UserAction deserialize(JsonElement json, Type typeOfT, 
     JsonDeserializationContext context) throws JsonParseException { 
     return new UserAction(UUID.fromString(json.getAsString()); 
} 

GsonBuilder gson = new GsonBuilder(); 
gson.registerTypeAdapter(UserAction.class, new UserActionDeserializer()); 

Tenga en cuenta que este código no se ha probado.

+0

estoy comprobando que ahora, gracias por la punta. – frail

0
gson.registerTypeAdapter(DateTime.class, new DateTimeDeserializer()); 

private class DateTimeDeserializer implements JsonDeserializer<DateTime> { 
    public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 
     throws JsonParseException { 
    return new DateTime(json.getAsJsonPrimitive().getAsString()); 
    } 
} 
+10

[Copiar y pegar] (http://sites.google.com/site/gson/gson-user-guide#TOC-Writing-an-Instance-Creator). Un poco cojo me preguntas;) –

10

Otro enfoque para resolver este problema sería la de aprovechar el hecho de que durante la deserialización Gson se clobber los valores establecidos por los constructores con los nuevos valores que se encuentran en el JSON, y así sólo tiene que utilizar un InstanceCreator, que existe específicamente "para crear instancias de una clase que no define un constructor sin argumentos". Este enfoque funciona especialmente bien cuando el constructor que se va a utilizar solo asigna valores de parámetros a los campos, y no realiza ninguna comprobación de validez ni realiza ningún procesamiento significativo basado en estado.

Además, este enfoque no requiere una deserialización personalizada adicional; no es necesaria la implementación personalizada de JsonDeserializer. Esto puede ser ventajoso para situaciones en las que la introducción de un deserializador personalizado para resolver un pequeño problema requiere el procesamiento "manual" de otros elementos JSON en las proximidades, lo que podría ser no trivial.

Con eso dicho, aquí hay una solución de trabajo que utiliza el constructor preferido UserAction, pero lo pasa solo una referencia nula. El valor real del JSON se establece más tarde. (Gson no le importa que el campo uuid se supone que es definitiva.)

import java.lang.reflect.Type; 
import java.util.UUID; 

import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 
import com.google.gson.InstanceCreator; 

public class Foo 
{ 
    public static void main(String[] args) 
    { 
    UserAction action = new UserAction(UUID.randomUUID()); 
    action.setUserId("user1"); 

    String json = new Gson().toJson(action); 
    System.out.println(json); 

    GsonBuilder gsonBuilder = new GsonBuilder(); 
    gsonBuilder.registerTypeAdapter(UserAction.class, new UserActionInstanceCreator()); 
    Gson gson = gsonBuilder.create(); 
    UserAction actionCopy = gson.fromJson(json, UserAction.class); 
    System.out.println(gson.toJson(actionCopy)); 
    } 
} 

class UserActionInstanceCreator implements InstanceCreator<UserAction> 
{ 
    @Override 
    public UserAction createInstance(Type type) 
    { 
    return new UserAction(null); 
    } 
} 

class UserAction 
{ 
    private final UUID uuid; 
    private String userId; 

    public UserAction() 
    { 
    throw new RuntimeException("this constructor is not used"); 
    } 

    public UserAction(UUID uuid) 
    { 
    this.uuid = uuid; 
    } 

    void setUserId(String userId) 
    { 
    this.userId = userId; 
    } 
} 
+0

buena manera, gracias – frail

Cuestiones relacionadas