web-dev-qa-db-ja.com

Java Gsonシリアル化中にフィールドを除外する

ConfigInstanceと_password_hash_を含むpasswordクラスがあります。次に、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に設定しました。

しかし、次のコードを実行します:

_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 [〜#〜] が機能しないように見えるので、私は今のところかなり無知であり、助けをいただければ幸いです。

前もって感謝します。

21
ThexBasic

この結果を取得するには、すべてのフィールドに@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 を設定してこれを実現する可能性があります。

30
bosco

これは別の方法です。

シリアル化:

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

特定のフィールドがシリアル化されないようにする場合は、一時的なキーワードを指定します

private transient String database_pass;

詳細については、 https://sites.google.com/site/gson/gson-user-guide#TOC-Finer-Points-with-Objects をご覧ください。

17
kPieczonka

@utkusonmezこの答えは、言及された方法が間違っているにもかかわらず機能します。 「addDeserializationExclusionStrategy」の代わりに「addSerializationExclusionStrategy」を使用する必要があります

答えは次のようになります

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

シリアライゼーションのみまたはデシリアライゼーションのみを無効にする場合は、@Exposeアノテーションの属性、例:

@Expose(serialize = false, deserialize = true)

デフォルトのオプションはtrueであるため、ここでは逆シリアル化は不要です。

5
Jakub Turcovsky

それは遅い答えですが、誰かを助けるかもしれません。

@Expose(serialize = false, deserialize = false)を実行するか、必要なことだけを行う必要があります。

serializedeserializetrueがある場合、@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"
}
1
Klotzi111

以下に、@ Exposeアノテーションや除外ストラテジーを使用せずに、1行のコードのみを使用した非常にシンプルなソリューションを示します。

Gsonに実装されているデフォルトの動作は、 nullオブジェクトフィールドは無視されます です。したがって、シリアル化する前にパスワードフィールドをnullに設定するだけです。

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