'Java to JSON: Specify which fields get excluded for each conversion
As mentioned here, I know that I can convert Java objects to JSON (with Jackson)
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(objectToBeConverted);
I know that I can exclude fields from being included in the JSON string using the @JsonIgnore annotation, but what if I want to convert the same class to JSON multiple times, but each time choosing different fields to ignore?
For example, if I have a class
class Foo {
int a;
int b;
...
}
can I do something like
Foo foo = new Foo();
String json1 = ow.writeValueAsString(foo).excludeField('b');
String json2 = ow.writeValueAsString(foo).excludeField('a');
so that the resulting strings look like
// json1
{
a: 1234
}
// json2
{
b: 5678
}
If Jackson can't do it, maybe Gson can? Or another library?
Solution 1:[1]
You can try using different mix-in interfaces. I found two ways to do this.
Use methods for reading properties. You can then create a mix-in class that only defines the properties to exclude:
public interface ExludeA { @JsonIgnore int getA(); }Use
@JsonIncludePropertiesto not tell which properties to exclude, but which properties to include:@JsonIncludeProperties({ "b", "c" }) public interface ExludeA { }
In both cases, add that mix-in to the object mapper:
objectMapper.addMixIn(Foo.class, ExcludeA.class);
There is one very, very important thing though - you must use a new ObjectMapper for each mix-in. If you use an ObjectMapper instance to serialize a Foo instance without mix-ins, then adding the mix-in won't help. That's probably because ObjectMapper instances cache some stuff.
Solution 2:[2]
Here is a simple approach if you could box up all primitive type in Foo.
For example: int -> Integer, boolean -> Boolean
@JsonInclude(Include.NON_NULL)
class Foo {
Integer a;
Integer b;
...
}
Then, just make a copy of Foo and set the property which you want to ignore to null.
Foo foo = new Foo();
foo.setA(1234);
foo.setB(5678);
Foo foo1 = objectMapper.readValue(objectMapper.writeValueAsString(foo), Foo.class); // make a copy of Foo
foo1.setB(null); // force to ignore B
String json1 = ow.writeValueAsString(foo1); // it will be {a:1234}
Solution 3:[3]
There is multiple solution based on your need:
First:
You can just define two different DTO for your purpose and every time you need to each one just use it.
Second:
You can use @JsonInclude(JsonInclude.Include.NON_NULL) annotation for the properties:
class Foo {
@JsonInclude(JsonInclude.Include.NON_NULL)
int a;
@JsonInclude(JsonInclude.Include.NON_NULL)
int b;
}
P.S: You can use this annotation on class level as:
@JsonInclude(JsonInclude.Include.NON_NULL)
class Foo {
int a;
int b;
}
Third:
Use can define a filter to ignore properties based on different conditions.
Define a simple class for your filter:
public class YourConditionalFilter {
@Override
public boolean equals(int a) {
return a == 1234;
}
}
And then add this filter as annotation on top of the property:
@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = YourConditionalFilter.class)
int a;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Rob Spoor |
| Solution 2 | |
| Solution 3 |
