Java Gson Исключить поля во время сериализации

У меня есть класс ConfigInstance, который содержит password и a password_hash. Теперь я хочу сериализовать объект с помощью gson, но исключить поле 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 */}
}

Как вы можете видеть, я попытался использовать @Expose(serialize = false), но он ничего не делает. Также я уже установил поле в приватное, так как понял, что это "переопределит" @Expose

но выполняется следующий код:

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

все еще приводит к следующему содержимому файла без ошибок:

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

Так что я делаю неправильно? Я довольно невнятный прямо сейчас и буду признателен за любую помощь, поскольку ЭТО, похоже, не работает.

Спасибо заранее.

Ответ 1

Чтобы получить этот результат, вам необходимо аннотировать все поля с помощью @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;

И настройте Gson только для того, чтобы выставлять аннотированные поля и игнорировать остальные, как показано ниже:

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

Затем вы получите:

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

Кроме того, при десериализации строки у вас все равно будет атрибут пароля.


Тем не менее, у вас есть возможность настроить Gson Serializer, чтобы выполнить это.

Ответ 2

Если вам нравится, чтобы определенное поле не было сериализованным, дайте ему ключевое слово переходного периода

private transient String database_pass;

посетите https://sites.google.com/site/gson/gson-user-guide#TOC-Finer-Points-with-Objects для получения дополнительной информации

Ответ 3

Это другой способ.

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();

Ответ 4

Если вы хотите отключить только сериализацию или только десериализацию, вы можете играть с атрибутами аннотации @Expose, например:

@Expose(serialize = false, deserialize = true)

Значение по умолчанию - true, поэтому здесь не требуется десериализация.

Ответ 5

@utkusonmez Этот ответ работает, хотя упомянутый метод неверен. Он должен использовать 'addSerializationExclusionStrategy' вместо 'addDeserializationExclusionStrategy'

Итак, ответ будет выглядеть как

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*))

Ответ 6

Вы можете сделать трюк с этим:

Gson gson = new GsonBuilder()
            .excludeFieldsWithModifiers(Modifier.STATIC)
            .create();

Затем во всех полях, которые вы хотите выделить из объекта, просто добавьте модификатор "статический"

@Expose(serialize = false)
private static String database_pass;

Вы можете использовать модификатор Transient или что-то вам подходит