2015-05-13 13 views
13

Sto usando Spring 4 MVC con Jackson 2 per il mio servizio. Per una delle operazioni Ho un oggetto richiesta che ha un attributo dove la parola conduce caso cammello questa è solo una lettera in lunghezza:Perché Jackson 2 non riconosce la prima lettera maiuscola se la parola chiave del cammello è lunga una sola lettera?

private String aLogId; 

Questa classe ha i getter e setter nome appropriato:

public String getALogId() { return aLogId; } 
public void setALogId(String aLogId) { this.aLogId = aLogId; } 

Tuttavia, quando tento di inviare una richiesta a questo servizio utilizzando la proprietà JSON corrispondente:

{"aLogId":"This is a log id"} 

sto ricevendo una risposta 500 dal framework Spring dicendo il campo non viene riconosciuto e la mia classe controller non viene mai chiamato:

Impossibile leggere JSON: campo non riconosciuto "aLogId" (classe

Tuttavia, quando cambio la "L" in minuscolo, la richiesta viene deserializzato come previsto e la mia classe controller è colpito:

{"alogId":"This is a log id"} 

Perché Jackson si aspettano che la "L" di essere minuscolo quando è ovviamente la seconda parola nel caso cammello convenzione per l'attributo e destinato a essere in maiuscolo? È perché la prima parola è lunga solo una lettera?

Ci sono altri attributi nell'oggetto richiesta dove la prima parola è più di una lettera e quelli attribuiti non affrontano questo stesso problema con la mancata corrispondenza nel caso.

+0

che sarebbe un bug interessante. che dire di una parola a lettera singola nel mezzo, come 'logAId' - fallirebbe anche tu? – ZhongYu

+2

Questo problema scompare se si rinomina getter e setter su 'setaLogId' e' getaLogId'. Ciò nonostante, nonostante la convenzione vola. C'è sicuramente qualcosa di "buggato" quando hai parole singole. – Leon

risposta

20

Il problema che si sta verificando è dovuto al fatto che Jackson utilizza le convenzioni di denominazione Java Bean, per individuarne le proprietà Json in una classe Java.

Ecco uno reference del problema specifico che si vede, la raccomandazione non è di capitalizzare nessuna delle prime due lettere nel proprio campo. Se si utilizza un IDE come IntelliJ o Eclipse e lasciare che l'IDE genera i setter per voi, si noterà lo stesso "comportamento" si verifica, si finirà con i seguenti metodi:

public void setaLogId(String aLogId) { 
    this.aLogId = aLogId; 
} 

public String getaLogId() { 
    return aLogId; 
} 

Quindi, quando si cambia la "L" alla lettera minuscola Jackson è stata in grado di capire il campo che si voleva mappare.

Detto quanto sopra, si ha ancora l'alternativa di utilizzare il "aLogId" nome del campo e fare Jackson funziona tutto ciò che dovete fare è utilizzare il @JsonProperty annotazioni con il aLogId in esso.

@JsonProperty("aLogId") 
private String aLogId; 

Il seguente codice di prova è quello di mostrare come questo funzionerà:

import com.fasterxml.jackson.annotation.JsonProperty; 
import com.fasterxml.jackson.databind.ObjectMapper; 

public class Test { 

    @JsonProperty("aLogId") 
    private String aLogId; 

    public void setaLogId(String aLogId) { 
     this.aLogId = aLogId; 
    } 

    public String getaLogId() { 
     return aLogId; 
    } 

    public static void main(String[] args) { 

     ObjectMapper objectMapper = new ObjectMapper(); 

     Test test = new Test(); 

     test.setaLogId("anId"); 

     try { 
      System.out.println("Serialization test: " + objectMapper.writeValueAsString(test)); 


      String json = "{\"aLogId\":\"anotherId\"}"; 

      Test anotherTest = objectMapper.readValue(json, Test.class); 

      System.out.println("Deserialization test: " +anotherTest.getaLogId()); 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 
} 

L'uscita del test è:

Serialization test: {"aLogId":"anId"}

Deserialization test: anotherId

+1

Questo aiuta. Curioso però, nella specifica 8.8 di Java Bean, in realtà menzionano se le prime due lettere sono maiuscole, ma lasciano in pace, quindi Jackson dovrebbe prenderlo come ALogId invece di alogId. Allora, Jackson si sta allontanando dalle specifiche Java Bean? In entrambi i casi, questa è un'ottima risposta e mi ha indicato nella direzione corretta. Grazie e accettato. – Hazok

+0

Sto usando Jackson 2.8.8 e ho lo stesso problema. Ma quando provo la vostra soluzione (anotating con @JsonProperty (il campo "aLogId" "aLogId")), ricevo due campi JSON: { \t "aLogId": "ANID", \t "alogId": "ANID" } Quindi il campo è duplicato, che non è corretto! Chiunque nella stessa situazione? – Alberthoven

+0

Una soluzione eccezionale. molte grazie – Murwa

0

mia comprensione è che Jackson usa di default il proprio nome conventio n, che è molto vicino, ma non esattamente lo stesso, alla convenzione di denominazione Java Bean. Un'opzione MapperFeature, MapperFeature.USE_STD_BEAN_NAMING, è stata aggiunta in Jackson 2.5.0 per indicare a Jackson di utilizzare la convenzione di denominazione Java Bean - vedere Jackson Issue 653. Per compatibilità con le versioni precedenti, il valore predefinito per MapperFeature.USE_STD_BEAN_NAMING è falso.

1

Questo ha funzionato per me; @JsonProperty annotation su getter!

import com.fasterxml.jackson.annotation.JsonProperty; 

public class PaytmRequestJson { 
    private String ORDERID; 
    private String MID; 
    private String CHECKSUMHASH; 

    @JsonProperty("ORDERID") 
    public String getORDERID() { 
     return ORDERID; 
    } 

    public void setORDERID(String ORDERID) { 
     this.ORDERID = ORDERID; 
    } 

    @JsonProperty("MID") 
    public String getMID() { 
     return MID; 
    } 

    public void setMID(String MID) { 
     this.MID = MID; 
    } 

    @JsonProperty("CHECKSUMHASH") 
    public String getCHECKSUMHASH() { 
     return CHECKSUMHASH; 
    } 

    public void setCHECKSUMHASH(String CHECKSUMHASH) { 
     this.CHECKSUMHASH = CHECKSUMHASH; 
    } 
} 
Problemi correlati