簡體   English   中英

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

[英]Java Gson Exclude fields during serialization

我有一個ConfigInstance類,其中包含passwordpassword_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"
}

那么我做錯了什么? 我現在很無能為力,感謝任何幫助,因為似乎不起作用。

提前致謝。

要獲得此結果,您需要使用@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來實現這一目標。

這是另一種方式。

系列化:

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

如果您希望特定字段不被序列化,請為其提供一個臨時關鍵字

private transient String database_pass;

有關更多信息,請訪問https://sites.google.com/site/gson/gson-user-guide#TOC-Finer-Points-with-Objects

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

如果要僅禁用序列化或僅禁用反序列化,則可以使用@Expose注釋的屬性,例如:

@Expose(serialize = false, deserialize = true)

默認選項為true,因此這里不需要反序列化。

這是一個遲到的答案,但它可能會幫助某人。

你只需要執行@Expose(serialize = false, deserialize = false)或者你想要的。

如果你有serializedeserialize serialize true那么根本不需要@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"
}

這是一個非常簡單的解決方案,只需一行代碼,沒有任何@Expose注釋或排除策略。

在Gson中實現的默認行為是忽略空對象字段 因此,您需要做的就是在序列化之前將密碼字段設置為null。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM