简体   繁体   English

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

[英]Java Gson Exclude fields during serialization

I have a ConfigInstance class which contains a password and a password_hash . 我有一个ConfigInstance类,其中包含passwordpassword_hash Now I want to serialize the object using gson but exclude the password field. 现在我想使用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. 正如您所看到的,我尝试过使用@Expose(serialize = false)但它似乎没有做任何事情。 Also I already set the field to private since I figured that this would "override" the @Expose 此外,我已经将该字段设置为私有,因为我认为这将“覆盖” @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 THIS doesn't seem to work. 我现在很无能为力,感谢任何帮助,因为似乎不起作用。

Thanks in advance. 提前致谢。

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. 此外,在对字符串进行反序列化时,您仍将拥有密码属性。


Still, you have the possibility to configure a Gson Serializer to accomplish this. 不过,您仍然可以配置Gson Serializer来实现这一目标。

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

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-Objects for more information 有关更多信息,请访问https://sites.google.com/site/gson/gson-user-guide#TOC-Finer-Points-with-Objects

@utkusonmez This answer works albeit the method mentioned is wrong. @utkusonmez这个答案虽然提到的方法是错误的,但仍然有效。 It should be using 'addSerializationExclusionStrategy' instead of 'addDeserializationExclusionStrategy' 它应该使用'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*))

If you want to disable only serialization or only deserialization, you can play with @Expose annotation's attributes, eg: 如果要仅禁用序列化或仅禁用反序列化,则可以使用@Expose注释的属性,例如:

@Expose(serialize = false, deserialize = true)

Default option is true, so deserialize is unnecessary here. 默认选项为true,因此这里不需要反序列化。

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 serialize and deserialize true its not nesseccary to have @Expose at all. 如果你有serializedeserialize serialize true那么根本不需要@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"
}

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 . 在Gson中实现的默认行为是忽略空对象字段 So, all you need to do is set the password field to null before serializing. 因此,您需要做的就是在序列化之前将密码字段设置为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