简体   繁体   中英

Java Gson Exclude fields during serialization

I have a ConfigInstance class which contains a password and a password_hash . Now I want to serialize the object using gson but exclude the password field.

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

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 :

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 = 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.

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

@utkusonmez This answer works albeit the method mentioned is wrong. It should be using 'addSerializationExclusionStrategy' instead of '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(serialize = false, deserialize = true)

Default option is true, so deserialize is unnecessary here.

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.

If you have serialize and deserialize true its not nesseccary to have @Expose at all.

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

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

Your ConfigInstance Class will look like follows

{
  "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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM