2012-09-26 3 views
10

Ho una classe con le seguenti annotazioni:Jersey/Jackson @JsonIgnore sul setter

class A { 
public Map<String,List<String>> references; 

@JsonProperty 
public Map<String,List<String>> getReferences() { 
... 
} 

@JsonIgnore 
public void setReferences(Map<String,List<String>>) { 
} 
... 
} 
} 

Quello che cerco è di ignorare il JSON sulla deserializzazione. Ma non funziona. Sempre quando arriva la stringa JSON, la lib di Jackson riempie l'attributo referenze. Se uso solo l'annotazione @JsonIgnore, il getter non funziona. Ci sono soluzioni per questo problema?

Grazie

risposta

0

posso solo pensare a una soluzione non-Jackson, per usare una classe base che non ha riferimenti per la mappatura e poi gettato alla classe reale:

// expect a B on an incoming request 
class B { 
// ... 
} 

// after the data is read, cast to A which will have empty references 
class A extends B { 
public Map<String,List<String>> references; 
} 

Perché invii persino i riferimenti se non li vuoi?

Oppure i dati in arrivo dalle tue mani e vuoi solo evitare l'eccezione di mappatura che ti dice che Jackson non riesce a trovare una proprietà da impostare per i riferimenti in entrata? Per questo usiamo una classe base che tutte le nostre classi del modello JSON ereditano:

public abstract class JsonObject { 

    @JsonAnySetter 
    public void handleUnknown(String key, Object value) { 

     // for us we log an error if we can't map but you can skip that 
     Log log = LogFactory.getLog(String.class);  
     log.error("Error mapping object of type: " + this.getClass().getName());  
     log.error("Could not map key: \"" + key + "\" and value: \"" + "\"" + value.toString() + "\""); 

    } 

Poi nel POJO si aggiunge @JsonIgnoreProperties in modo che le proprietà in arrivo avranno trasmesso al handleUnknown()

@JsonIgnoreProperties 
class A extends JsonObject { 
    // no references if you don't need them 
} 

edit

This SO Thread descrive come utilizzare Mixins. Questa potrebbe essere la soluzione, se vuoi mantenere la tua struttura esattamente com'è, ma non l'ho ancora provata.

+0

Proprio così. I dati in arrivo non sono nelle nostre mani. Ma i client inviano sempre un attributo referenze nel formato corretto in modo che handleUnknown non venga mai chiamato. – guerilla

+0

Ah, il mio male, ho dimenticato un po 'di informazioni. È necessario '@ JsonIgnoreProperties' nel POJO se si desidera ignorare i dati in entrata. Aggiornerò il mio post (PS: usiamo questo per consumare la risorsa REST di Facebook e tutte le proprietà inviate da facebook che non sono contenute nel nostro POJO verranno appena registrate e quindi decidiamo se vogliamo aggiungerle o meno) – Pete

+0

Ma i riferimenti sono nel mio POJO quindi corrisponde sempre al setter – guerilla

15

Penso che ci siano due elementi chiave che dovrebbero consentire di avere "raccolte di sola lettura" come desiderato. In primo luogo, oltre a ignorare il setter, assicurarsi che il campo è anche contrassegnato con @JsonIgnore:

class A { 

    @JsonIgnore 
    public Map<String,List<String>> references; 

    @JsonProperty 
    public Map<String,List<String>> getReferences() { ... } 

    @JsonIgnore 
    public void setReferences(Map<String,List<String>>) { ... } 

} 

In secondo luogo, al fine di evitare che i getter venga utilizzato come setter, disattivare la USE_GETTERS_AS_SETTERS funzione:

ObjectMapper mapper = new ObjectMapper(); 
mapper.disable(MapperFeature.USE_GETTERS_AS_SETTERS); 
+0

ho scioccamente ignorato il tuo primo consiglio e non ha contrassegnato il campo come ignorato, poiché è privato nel mio caso. Tuttavia, dovevo farlo comunque, per farlo funzionare correttamente. È giusto o un equivoco dalla mia parte? Se è così, forse vale la pena indicarlo esplicitamente nella risposta. –

4

È necessario accertarsi che vi sia l'annotazione @JsonIgnore a livello di campo e sul setter e annotata con getterProperty su getter.

public class Echo { 

    @Null 
    @JsonIgnore 
    private String doNotDeserialise; 

    private String echo; 

    @JsonProperty 
    public String getDoNotDeserialise() { 
     return doNotDeserialise; 
    } 

    @JsonIgnore 
    public void setDoNotDeserialise(String doNotDeserialise) { 
     this.doNotDeserialise = doNotDeserialise; 
    } 

    public String getEcho() { 
     return echo; 
    } 

    public void setEcho(String echo) { 
     this.echo = echo; 
    } 
} 

@Controller 
public class EchoController { 

@ResponseBody 
@RequestMapping(value = "/echo", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) 
    public Echo echo(@RequestBody @Valid Echo echo) { 
     if (StringUtils.isEmpty(echo.getDoNotDeserialise())) { 
      echo.setDoNotDeserialise("Value is set by the server, not by the client!"); 
     } 

     return echo; 
    } 
} 
  • Se si invia una richiesta JSON con un valore “doNotDeserialise” impostato su qualcosa, quando JSON è deserialised a un oggetto che sarà impostato su null (se non ho messo un vincolo di validazione sul campo in modo sarà errore fuori)
  • Se si imposta il valore “doNotDeserialise” a qualcosa sul server allora sarà serializzato correttamente per JSON e spinto al cliente
3

ho usato @JsonIgnore sul mio getter e didn' t lavoro e non ho potuto configurare il mapper (I w come usare i fornitori di Jackson Jaxrs).Questo ha funzionato per me:

@JsonIgnoreProperties(ignoreUnknown = true, value = { "actorsAsString", 
    "writersAsString", "directorsAsString", "genresAsString" }) 
0

Come di Jackson 2.6, c'è un modo nuovo e migliore per definire read-only e write-only proprietà, utilizzando JsonProperty#access() annotazione. Si consiglia di utilizzare le annotazioni separate JsonIgnore e JsonProperty.

@JsonProperty(access = JsonProperty.Access.READ_ONLY) 
public Map<String,List<String>> references;