有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java Gson在序列化期间排除字段

我有一个ConfigInstance类,它包含一个password和一个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),但它似乎没有任何作用。此外,我已经将该字段设置为private,因为我认为这将“覆盖”@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似乎不起作用

提前谢谢


共 (6) 个答案

  1. # 1 楼答案

    这是一个迟来的答案,但它可能会帮助一些人

    你只需要做@Expose(serialize = false, deserialize = false)或者做你想做的事

    如果你有serializedeserialize{},那么根本没有必要有@Expose

    创建此类:

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

    然后用GsonBuilder构建Gson

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

    您的ConfigInstance类如下所示

    {
      "database_address": "127.0.0.1",
      "database_port": 1521,
      "database_user": "test",
      "database_pass_hash": "B9FE2C011B59F0D0D383D70073E48A19"
    }
    
  2. # 3 楼答案

    如果只想禁用序列化或反序列化,可以使用@Expose注释的属性,例如:

    @Expose(serialize = false, deserialize = true)
    

    默认选项为true,因此这里不需要反序列化

  3. # 4 楼答案

    这是另一种方式

    序列化:

    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 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. # 5 楼答案

    @utkusonmez 尽管所提到的方法是错误的,但这个答案仍然有效。 它应该使用“AddSerializationExclutionStrategy”而不是“AddDeserializationExclutionStrategy”

    所以答案看起来是这样的

    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*))
    
  5. # 6 楼答案

    为了得到这个结果,需要用@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"
    }
    

    此外,当反序列化字符串时,您仍然具有password属性


    不过,您仍然可以配置一个Gson Serializer来实现这一点