Pode ser uma duplicata. Mas não consigo encontrar uma solução para o meu problema.
Eu tenho uma aula
public class MyResponse implements Serializable {
private boolean isSuccess;
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}
}
Getters e setters são gerados pelo Eclipse.
Em outra classe, defino o valor como true e o escrevo como uma string JSON.
System.out.println(new ObjectMapper().writeValueAsString(myResponse));
Em JSON, a chave está chegando {"success": true}
.
Eu quero a chave como isSuccess
ela mesma. Jackson está usando o método setter durante a serialização? Como transformar a chave no próprio nome do campo?
isSuccess
o nome do seu método deve serisIsSuccess
eu achoSetSuccess
já que foi gerado pelo Eclipse. (Seguindo um padrão)Respostas:
Esta é uma resposta um pouco tardia, mas pode ser útil para qualquer pessoa que visite esta página.
Uma solução simples para alterar o nome que Jackson usará ao serializar para JSON é usar a anotação @JsonProperty , portanto, seu exemplo seria:
public class MyResponse implements Serializable { private boolean isSuccess; @JsonProperty(value="isSuccess") public boolean isSuccess() { return isSuccess; } public void setSuccess(boolean isSuccess) { this.isSuccess = isSuccess; } }
Isso seria então serializado para JSON como
{"isSuccess":true}
, mas tem a vantagem de não precisar modificar o nome do método getter.Observe que, neste caso, você também pode escrever a anotação,
@JsonProperty("isSuccess")
pois ela só tem um únicovalue
elementofonte
Recentemente, encontrei esse problema e foi isso que descobri. Jackson inspecionará qualquer classe que você passar para ele em busca de getters e setters e usará esses métodos para serialização e desserialização. O que segue "get", "is" e "set" nesses métodos será usado como a chave para o campo JSON ("isValid" para getIsValid e setIsValid).
public class JacksonExample { private boolean isValid = false; public boolean getIsValid() { return isValid; } public void setIsValid(boolean isValid) { this.isValid = isValid; } }
Da mesma forma, "isSuccess" se tornará "sucesso", a menos que seja renomeado para "isIsSuccess" ou "getIsSuccess"
Leia mais aqui: http://www.citrine.io/blog/2015/5/20/jackson-json-processor
fonte
Usando as duas anotações abaixo, força o JSON de saída a incluir
is_xxx
:@get:JsonProperty("is_something") @param:JsonProperty("is_something")
fonte
Você pode configurar o seu da
ObjectMapper
seguinte maneira:mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() { @Override public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { if(method.hasReturnType() && (method.getRawReturnType() == Boolean.class || method.getRawReturnType() == boolean.class) && method.getName().startsWith("is")) { return method.getName(); } return super.nameForGetterMethod(config, method, defaultName); } });
fonte
Quando você estiver usando Kotlin e classes de dados:
data class Dto( @get:JsonProperty("isSuccess") val isSuccess: Boolean )
Talvez seja necessário adicionar
@param:JsonProperty("isSuccess")
se você for desserializar JSON também.fonte
Com base na resposta de Utkarsh ..
Nomes de getter menos get / is é usado como o nome JSON.
public class Example{ private String radcliffe; public getHarryPotter(){ return radcliffe; } }
é armazenado como {"harryPotter": "qualquer que seja YouGaveHere"}
Para desserialização, Jackson verifica o setter e o nome do campo. Para a String Json {"palavra1": "exemplo"} , ambas as opções abaixo são válidas.
public class Example{ private String word1; public setword2( String pqr){ this.word1 = pqr; } } public class Example2{ private String word2; public setWord1(String pqr){ this.word2 = pqr ; } }
Uma questão mais interessante é qual ordem Jackson considera para desserialização. Se eu tentar desserializar {"word1": "myName"} com
public class Example3{ private String word1; private String word2; public setWord1( String parameter){ this.word2 = parameter ; } }
Não testei o caso acima, mas seria interessante ver os valores de palavra1 e palavra2 ...
Observação: usei nomes drasticamente diferentes para enfatizar quais campos devem ser iguais.
fonte
Eu não queria mexer com algumas estratégias de nomenclatura personalizadas, nem recriar alguns acessadores.
Quanto menos código, mais feliz eu fico.
Isso funcionou para nós:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; @JsonIgnoreProperties({"success", "deleted"}) // <- Prevents serialization duplicates public class MyResponse { private String id; private @JsonProperty("isSuccess") boolean isSuccess; // <- Forces field name private @JsonProperty("isDeleted") boolean isDeleted; }
fonte
existe outro método para este problema.
basta definir uma nova subclasse que estende PropertyNamingStrategy e passá-la para a instância ObjectMapper.
aqui está um snippet de código que pode ser mais útil:
mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() { @Override public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { String input = defaultName; if(method.getName().startsWith("is")){ input = method.getName(); } //copy from LowerCaseWithUnderscoresStrategy if (input == null) return input; // garbage in, garbage out int length = input.length(); StringBuilder result = new StringBuilder(length * 2); int resultLength = 0; boolean wasPrevTranslated = false; for (int i = 0; i < length; i++) { char c = input.charAt(i); if (i > 0 || c != '_') // skip first starting underscore { if (Character.isUpperCase(c)) { if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_') { result.append('_'); resultLength++; } c = Character.toLowerCase(c); wasPrevTranslated = true; } else { wasPrevTranslated = false; } result.append(c); resultLength++; } } return resultLength > 0 ? result.toString() : input; } });
fonte
A resposta aceita não funcionará para o meu caso.
No meu caso, a classe não é minha. A classe problemática vem de dependências de terceiros, então não posso simplesmente adicionar
@JsonProperty
anotações a ela.Para resolvê-lo, inspirado na resposta de @burak acima, criei um custom
PropertyNamingStrategy
como segue:mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() { @Override public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { if (method.getParameterCount() == 1 && (method.getRawParameterType(0) == Boolean.class || method.getRawParameterType(0) == boolean.class) && method.getName().startsWith("set")) { Class<?> containingClass = method.getDeclaringClass(); String potentialFieldName = "is" + method.getName().substring(3); try { containingClass.getDeclaredField(potentialFieldName); return potentialFieldName; } catch (NoSuchFieldException e) { // do nothing and fall through } } return super.nameForSetterMethod(config, method, defaultName); } @Override public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { if(method.hasReturnType() && (method.getRawReturnType() == Boolean.class || method.getRawReturnType() == boolean.class) && method.getName().startsWith("is")) { Class<?> containingClass = method.getDeclaringClass(); String potentialFieldName = method.getName(); try { containingClass.getDeclaredField(potentialFieldName); return potentialFieldName; } catch (NoSuchFieldException e) { // do nothing and fall through } } return super.nameForGetterMethod(config, method, defaultName); } });
Basicamente, o que isso faz é, antes de serializar e desserializar, verificar na classe de destino / origem qual nome de propriedade está presente na classe, se é
isEnabled
ouenabled
propriedade.Com base nisso, o mapeador será serializado e desserializado para o nome da propriedade existente.
fonte
Você pode alterar o booleano primitivo para java.lang.Boolean (+ usar
@JsonPropery
)@JsonProperty("isA") private Boolean isA = false; public Boolean getA() { return this.isA; } public void setA(Boolean a) { this.isA = a; }
Funcionou excelente para mim.
fonte