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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40909205/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:59:17  来源:igfitidea点击:

Java Gson Exclude fields during serialization

javaserializationgson

提问by ThexBasic

I have a ConfigInstanceclass which contains a passwordand a password_hash. Now I want to serialize the object using gson but exclude the passwordfield.

我有一个ConfigInstance包含 apassword和 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 */}
}

As you can see, I have tried using @Expose(serialize = false)but it doesn't seem to do anything. Also I already set the field to private since I figured that this would "override" the @Expose

如您所见,我尝试使用,@Expose(serialize = false)但似乎没有任何作用。此外,我已经将该字段设置为私有,因为我认为这会“覆盖”@Expose

but running following code:

但运行以下代码:

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

still results in the following file content without Errors:

仍然会导致以下文件内容没有错误:

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

So what am I doing wrong? I am pretty clueless right now and would appreciate any help since THISdoesn't seem to work.

那么我做错了什么?我现在很无能,希望得到任何帮助,因为似乎不起作用。

Thanks in advance.

提前致谢。

采纳答案by bosco

In order to get this result, you need to annotate all the fields with the @Expose:

为了获得此结果,您需要使用以下内容注释所有字段@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;

And configure Gson to only expose fields that are annotated and ignore the rest as shown in the following:

并将 Gson 配置为仅公开已注释的字段并忽略其余字段,如下所示:

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

Then, you'll get:

然后,你会得到:

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

Also, when deserialising the string you'll still have the password attribute as well.

此外,在反序列化字符串时,您仍将拥有 password 属性。



Still, you have the possibility to configure a Gson Serializerto accomplish this.

尽管如此,您仍然可以配置Gson Serializer来完成此操作。

回答by kPieczonka

If you like particular field not be serialized give it a transient keyword

如果你喜欢特定的字段不被序列化,给它一个瞬态关键字

private transient String database_pass;

visit https://sites.google.com/site/gson/gson-user-guide#TOC-Finer-Points-with-Objectsfor more information

访问https://sites.google.com/site/gson/gson-user-guide#TOC-Finer-Points-with-Objects了解更多信息

回答by utkusonmez

This is another way.

这是另一种方式。

serialization:

序列化:

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

deserialization:

反序列化:

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

回答by Jakub Turcovsky

If you want to disable only serialization or only deserialization, you can play with @Exposeannotation's attributes, e.g.:

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

@Expose(serialize = false, deserialize = true)

Default option is true, so deserialize is unnecessary here.

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

回答by Olmstov

@utkusonmez This answer works albeit the method mentioned is wrong. It should be using 'addSerializationExclusionStrategy' instead of 'addDeserializationExclusionStrategy'

@utkusonmez 这个答案有效,尽管提到的方法是错误的。它应该使用“addSerializationExclusionStrategy”而不是“addDeserializationExclusionStrategy”

So the answer would look like

所以答案看起来像

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

回答by Klotzi111

It's a late answer but it may help someone.

这是一个迟到的答案,但它可能会帮助某人。

You only have to do the @Expose(serialize = false, deserialize = false)or just what you want.

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

If you have serializeand deserializetrueits not nesseccary to have @Exposeat all.

如果你有serialize而且deserializetrue根本没有必要@Expose

Create this Class:

创建这个类:

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

}

and then build Gson with GsonBuilder

然后用 GsonBuilder 构建 Gson

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

Your ConfigInstance Class will look like follows

您的 ConfigInstance 类将如下所示

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

回答by ntsh

Here's a very simple solution with just one line of code, without any @Expose annotation or exclusion strategy.

这是一个非常简单的解决方案,只有一行代码,没有任何 @Expose 注释或排除策略。

The default behaviour that is implemented in Gson is that null object fields are ignored. So, all you need to do is set the password field to null before serializing.

Gson 中实现的默认行为是忽略空对象字段。因此,您需要做的就是在序列化之前将密码字段设置为 null。

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