2016-12-01 5 views
12

У меня есть класс ConfigInstance, который содержит password и password_hash. Теперь я хочу сериализовать объект с помощью gson, но исключить поле password.Java Gson Исключить поля во время сериализации

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

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

Заранее спасибо.

ответ

16

Для того, чтобы получить этот результат, необходимо аннотировать все поля с @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 для достижения этой цели.

+0

Это работает отлично. Большое спасибо – ThexBasic

1

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

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

Тогда во всех областях, которые вы хотите excelude от объекта просто добавьте модификатор «статический»

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

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

+0

подход был бы хорошо, если бы я не стал бы иметь несколько экземпляров объекта. Поэтому использование статических полей не является вариантом. – ThexBasic

+0

, потому что для одного и того же объекта вы хотите заполнить атрибут несколько раз, а другие - нет? – cralfaro

+0

Тогда, возможно, вы могли бы создать 2 новых экземпляра, ConfigInstancePrivate и ConfigInstancePublic и определить атрибут пароля для каждого по своему усмотрению, тогда в вашей логике использование экземпляра вам лучше подходит – cralfaro

7

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

private transient String database_pass; 

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

+2

, я тоже пробовал это, но проблема в том, что переходные поля полностью игнорируется Гсоном, также при десериализации. Поэтому в случае, если пароли будут модифицированы в файле, поле базы данных не будет назначаться при десериализации, – ThexBasic

6

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

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

Так полезный способ! – Tuby

3

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

@Expose(serialize = false, deserialize = true) 

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

3

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