web-dev-qa-db-fra.com

Jackson renomme le champ booléen primitif en supprimant "is"

Cela pourrait être un doublon. Mais je ne trouve pas de solution à mon problème.

J'ai un cours

public class MyResponse implements Serializable {

    private boolean isSuccess;

    public boolean isSuccess() {
        return isSuccess;
    }

    public void setSuccess(boolean isSuccess) {
        this.isSuccess = isSuccess;
    }
}

Les getters et les setters sont générés par Eclipse.

Dans une autre classe, je règle la valeur sur true et l'écris sous forme de chaîne JSON.

System.out.println(new ObjectMapper().writeValueAsString(myResponse));

En JSON, la clé arrive sous la forme {"success": true}.

Je veux la clé en tant que isSuccess elle-même. Jackson utilise-t-il la méthode de définition lors de la sérialisation? Comment faire de la clé le nom du champ lui-même?

40
iCode

Ceci est une réponse un peu tardive, mais peut être utile à toute autre personne visitant cette page.

Une solution simple pour changer le nom que Jackson utilisera pour la sérialisation en JSON consiste à utiliser l'annotation @JsonProperty , afin que votre exemple devienne:

public class MyResponse implements Serializable {

    private boolean isSuccess;

    @JsonProperty(value="isSuccess")        
    public boolean isSuccess() {
        return isSuccess;
    }

    public void setSuccess(boolean isSuccess) {
        this.isSuccess = isSuccess;
    }
}

Ceci serait alors sérialisé en JSON en tant que {"isSuccess":true}, mais présente l'avantage de ne pas avoir à modifier votre nom de méthode getter.

Notez que dans ce cas, vous pouvez également écrire l'annotation sous la forme @JsonProperty("isSuccess") car elle ne comporte que l'élément unique value.

60
Scott

J'ai récemment rencontré ce problème et c'est ce que j'ai trouvé. Jackson inspectera toutes les classes que vous lui transmettez pour les accesseurs et les installateurs, et utilisera ces méthodes pour la sérialisation et la désérialisation. Ce qui suit "get", "est" et "set" dans ces méthodes sera utilisé comme clé du champ JSON ("isValid" pour getIsValid et setIsValid).

public class JacksonExample {   

    private boolean isValid = false;

    public boolean getIsValid() {
        return isValid;
    }

    public void setIsValid(boolean isValid) {
        this.isValid = isValid;
    }
} 

De même, "isSuccess" deviendra "success", à moins d'être renommé "isIsSuccess" ou "getIsSuccess".

Lisez plus ici: http://www.citrine.io/blog/2015/5/20/jackson-json-processor

14
Utkarsha Padhye

Vous devez ajouter une configuration au mappeur d'objets Jackson, par exemple:

MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.getObjectMapper().disable(MapperFeature.AUTO_DETECT_IS_GETTERS);
3
borino

S'appuyant sur la réponse d'Utkarsh ..

Les noms des accesseurs moins get/is est utilisé comme nom JSON.

public class Example{
    private String radcliffe; 

    public getHarryPotter(){
        return radcliffe; 
    }
}

est stocké sous la forme {"harryPotter": "quel que soit votre choix"}  


Pour la désérialisation, Jackson vérifie à la fois le séparateur et le nom du champ . Pour le Json String {"Word1": "exemple"} , les deux éléments ci-dessous sont valides.

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 ; 
    }
}

Une question plus intéressante est de savoir quel ordre Jackson considère pour la désérialisation. Si j'essaie de désérialiser {"Word1": "myName"} with

public class Example3{
    private String Word1;
    private String Word2; 

    public setWord1( String parameter){
        this.Word2 = parameter ; 
    }
}

Je n'ai pas testé le cas ci-dessus, mais il serait intéressant de voir les valeurs de Word1 & Word2 ...

Remarque: j'ai utilisé des noms très différents pour souligner les champs devant être identiques.

1
Abhinav Vishak

Vous pouvez configurer votre ObjectMapper comme suit:

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);
            }
        });
1
burak emre

il existe une autre méthode pour résoudre ce problème.

il suffit de définir une nouvelle sous-classe, d'étendre PropertyNamingStrategy et de le transmettre à l'instance ObjectMapper.

voici un extrait de code peut être aider plus:

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;
        }
    });
1
eric

L'utilisation des deux annotations ci-dessous oblige le JSON de sortie à inclure is_xxx:

@get:JsonProperty("is_something")
@param:JsonProperty("is_something")
0
Fabio