web-dev-qa-db-fra.com

Java Gson Exclure les champs lors de la sérialisation

J'ai une classe ConfigInstance qui contient une password et un password_hash. Maintenant, je veux sérialiser l'objet à l'aide de gson mais exclure le champ password.

public class ConfigInstance {
    public String database_address;
    public int database_port;
    public String database_user;

    @Expose(serialize = false)
    private String database_pass;
    public String database_pass_hash;

    public String GetPass() { return database_pass; }

    public void Encrypt() { /* Creates the hash before serializing*/ }

    public void Decrypt() { /* Creates the password after deserializing */}
}

Comme vous pouvez le constater, j’ai essayé d’utiliser @Expose(serialize = false) mais cela ne semble rien faire. De plus, j'ai déjà défini le champ sur privé car je pensais que cela "écraserait" le @Expose

mais en exécutant le code suivant:

private void toFile(File file, ConfigInstance map) {
    map.Encrypt();
    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String jsonConfig = gson.toJson(map);
    FileWriter writer;
    try {
        writer = new FileWriter(file);
        writer.write(jsonConfig);
        writer.flush();
        writer.close();
    } catch (IOException e) {
        System.out.println("Error exporting config: " + e.toString());
    }
}

entraîne toujours le contenu du fichier suivant sans erreur:

{
  "database_address": "127.0.0.1",
  "database_port": 1521,
  "database_user": "test",
  "database_pass": "test1234",
  "database_pass_hash": "B9FE2C011B59F0D0D383D70073E48A19"
}

Alors qu'est-ce que je fais mal? Je suis assez désemparé en ce moment et apprécierais toute aide puisque CE ne semble pas fonctionner.

Merci d'avance.

17
ThexBasic

Pour obtenir ce résultat, vous devez annoter tous les champs avec le @Expose:

public class ConfigInstance {

    @Expose
    public String database_address;
    @Expose
    public int database_port;
    @Expose
    public String database_user;

    @Expose(serialize = false)
    private String database_pass;
    @Expose
    public String database_pass_hash;

Et configurez Gson pour n’exposer que les champs annotés et ignorer le reste, comme indiqué ci-dessous:

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setPrettyPrinting().create();

Ensuite, vous aurez:

{
  "database_address": "127.0.0.1",
  "database_port": 1521,
  "database_user": "test",
  "database_pass_hash": "B9FE2C011B59F0D0D383D70073E48A19"
}

De plus, lors de la désérialisation de la chaîne, vous aurez toujours l'attribut password.


Néanmoins, vous avez la possibilité de configurer un Gson Serializer pour accomplir cela.

26
bosco

C'est une autre façon.

sérialisation:

Gson gson = new GsonBuilder()
            .addSerializationExclusionStrategy(new ExclusionStrategy() {
                @Override
                public boolean shouldSkipField(FieldAttributes f) {
                    return f.getName().toLowerCase().contains("fieldName");
                }

                @Override
                public boolean shouldSkipClass(Class<?> aClass) {
                    return false;
                }
            })
            .create();

désérialisation:

Gson gson = new GsonBuilder()
            .addDeserializationExclusionStrategy(new ExclusionStrategy() {
                @Override
                public boolean shouldSkipField(FieldAttributes f) {
                    return f.getName().toLowerCase().contains("fieldName");
                }

                @Override
                public boolean shouldSkipClass(Class<?> aClass) {
                    return false;
                }
            })
            .create();
20
utkusonmez

Si vous aimez un domaine particulier ne pas être sérialisé, donnez-lui un mot clé transitoire. 

private transient String database_pass;

visitez https://sites.google.com/site/gson/gson-user-guide#TOC-Finer-Points-with-Objects pour plus d'informations

16
kPieczonka

@utkusonmez Cette réponse fonctionne même si la méthode mentionnée est incorrecte . Elle devrait utiliser 'addSerializationExclusionStrategy' au lieu de 'addDeserializationExclusionStrategy'

Donc, la réponse ressemblerait à

Gson gson = new GsonBuilder()
            .addSerializationExclusionStrategy(new ExclusionStrategy() {
                @Override
                public boolean shouldSkipField(FieldAttributes f) {
                    return f.getName().toLowerCase().contains("fieldName");
                }

                @Override
                public boolean shouldSkipClass(Class<?> aClass) {
                    return false;
                }
            })
            .create();

gson.toJson(*OBJ_TO_SERIALIZE*))
11
Olmstov

Si vous souhaitez désactiver uniquement la sérialisation ou la désérialisation, vous pouvez jouer avec les attributs de l'annotation @Expose, par exemple:

@Expose(serialize = false, deserialize = true)

L'option par défaut est true, la désérialisation est donc inutile ici.

3
Jakub Turcovsky

C'est une réponse tardive, mais cela peut aider quelqu'un.

Vous devez seulement faire @Expose(serialize = false, deserialize = false) ou juste ce que vous voulez.

Si vous avez serialize et deserializetrue, il n'est pas nécessaire d'avoir @Expose du tout.

Créer cette classe:

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.annotations.Expose;

public class NoModuleExclusionStrategy implements ExclusionStrategy {

    private final boolean deserialize;

    public NoModuleExclusionStrategy(boolean isdeserialize) {
        deserialize = isdeserialize;
    }

    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return false;
    }

    @Override
    public boolean shouldSkipField(FieldAttributes field) {
        return !(field.getAnnotation(Expose.class) == null || (deserialize ? field.getAnnotation(Expose.class).deserialize() : field.getAnnotation(Expose.class).serialize()));
    }

}

puis construisez Gson avec GsonBuilder

Gson gson = new GsonBuilder()
.addSerializationExclusionStrategy(new NoModuleExclusionStrategy(false))
.addDeserializationExclusionStrategy(new NoModuleExclusionStrategy(true))
.create();

Votre classe ConfigInstance ressemblera à ce qui suit

{
  "database_address": "127.0.0.1",
  "database_port": 1521,
  "database_user": "test",
  "database_pass_hash": "B9FE2C011B59F0D0D383D70073E48A19"
}
1
Klotzi111

Voici une solution très simple avec une seule ligne de code, sans stratégie d'annotation ou d'exclusion @Expose.

Le comportement par défaut implémenté dans Gson est que les champs d'objet null sont ignorés . Il suffit donc de définir le champ du mot de passe sur null avant la sérialisation.

map.setPassword(null); // or map.password = null;
String jsonConfig = gson.toJson(map); // This won't serialize null password field
0
ntsh