In the previous blog posts, you've learned a few techniques to control which model properties get (de)serialized. So far, this always has been on the property level. You can change the (de)serialization for one element at a time. In this blog post, we'll look at a way to set up more general rules to control which properties get converted.
Of course, this will not be the only post in our Gson series. If you're interested in the other topics, check out our series outline:
Gson Series Overview
- Mapping of Enums
- Mapping of Circular References
- Generics
- Custom Serialization for Simplification (Part 1)
- Changing the Default Serialization with Custom Serialization (Part 2)
- Custom Deserialization Basics
- Custom Instance Creator
- Customizing (De)Serialization via @JsonAdapter
- Custom Deserialization for Calculated Fields
- On-The-Fly-Parsing With Streams
- ProGuard Configuration
Go Beyond transient
and @Expose
with Exclusion Strategies
You've already learned about transient and @Expose, which changes the (de)serialization for single properties. In the next few minutes we'll look at more universal approach. Gson calls them ExclusionStrategies
. Of course, you have to set them via GsonBuilder
.
Before we go to the specific implementation, let's create a test model. We're going to use a new UserDate
model, which has several properties:
public class UserDate {
private String _name;
private String email;
private boolean isDeveloper;
private int age;
private Date registerDate = new Date();
}
Pay extra attention to the property types and their naming. It'll get important in a minute. Let's assume we want to kick out all properties, which are of the Date
or boolean
type. We can easily do this with ExclusionStrategies
. You can implement it via the GsonBuilder
:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return false;
}
@Override
public boolean shouldSkipClass(Class<?> incomingClass) {
return incomingClass == Date.class || incomingClass == boolean.class;
}
});
Gson gson = gsonBuilder.create();
UserDate user = new UserDate("Norman", "norman@futurestud.io", 26, true);
String usersJson = gson.toJson(user);
The ExclusionStrategy
class has two methods you can override. We only used the second option in the example above. We checked if the class is either of the type Date
or boolean
. If the property is of either type, the function will return true and Gson will ignore it. You can do any class checking in this method. The resulting JSON would only contain the string and int types:
{
"age": 26,
"email": "norman@futurestud.io",
"_name": "Norman"
}
The other method offers the option to exclude properties based on their declaration. For example, if we would want to exclude all properties which contain an underscore _
additionally to the rules above, you could use the following code:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getName().contains("_");
}
@Override
public boolean shouldSkipClass(Class<?> incomingClass) {
return incomingClass == Date.class || incomingClass == boolean.class;
}
});
Gson gson = gsonBuilder.create();
UserDate user = new UserDate("Norman", "norman@futurestud.io", 26, true);
String usersJson = gson.toJson(user);
This would result into a pretty short JSON:
{
"age": 26,
"email": "norman@futurestud.io"
}
You can use exclusion strategies for a lot of different scenarios. It makes it much easier if you've some universal system of specific (de)serialization exclusions. Please note that you can pass multiple exclusion strategies as a parameter.
If you don't see the point of the exclusion strategy at the moment, that's okay! We'll go much more in depth with more complex types soon. You'll see the value for sure once we moved onto writing our custom adapters. Luckily, with exclusion strategies you can set Gson to ignore any class.
Exclusion Strategies for Serialization or Deserialization Only
In the previous section, we've applied the exclusion strategy to both, serialization and deserialization. If you need an exclusion strategy for only serialization or deserialization, you can use these methods:
addSerializationExclusionStrategy()
addDeserializationExclusionStrategy()
.
The way these two methods work is identical to the previous general approach with setExclusionStrategies()
. You can implement and pass the same ExclusionStrategy
object.
Exclude Fields Based on Modifiers
As we've explained previously, all model fields with a transient
modifier are by default ignored during serialization and deserialization.
The GsonBuilder lets you change this behavior. With excludeFieldsWithModifiers()
you can customize which modifiers are not included during (de)serialization. The method expects one of the modifiers from the java.lang.reflect.Modifier class.
For example, you could have the following model:
public class UserModifier {
private String name;
private transient String email;
private static boolean isDeveloper;
private final int age;
}
If you would want to exclude all fields of the final
and static
type, but include the transient
field, you would need to configure Gson with the GsonBuilder like this:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.FINAL);
Gson gson = gsonBuilder.create();
UserModifier user = new UserModifier("Norman", "norman@fs.io", 26, true);
String usersJson = gson.toJson(user);
The code above would create this JSON:
{
"email": "norman@fs.io",
"name": "Norman"
}
Note how the Gson instance included the email
field, even though it's transient
. Calling the excludeFieldsWithModifiers()
method overwrites the default settings. We've only passed static
and final
, thus the transient
modifier will not be ignored. If you want that all fields are included, no matter of the modifiers, just pass an empty list to excludeFieldsWithModifiers()
.
Exclude Fields without @Expose
Finally, one option we're not big fans of, but will mention to give you all the options: excludeFieldsWithoutExposeAnnotation()
. As the method name suggests, this excludes all fields which don't have an @Expose annotation.
You can force your application models to have @Expose
annotations everywhere and make sure the developer thinks about which field gets (de)serialized.
Outlook
In this blog post, you've learned how you can exclude properties on a more general level. ExclusionStrategies
offers two options on how to exclude properties. You can filter based on the class type or the name of the property. There are additional more specialized exclusion strategies.
In the next blog post, we'll look at how flexible Gson is if the JSON isn't structured according to the standard.
If you've feedback or a question, let us know in the comments or on twitter @futurestud_io.
Make it rock & enjoy coding!