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?
CodePudding user response:
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;
CodePudding user response:
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
@JsonIncludeProperties
to 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.
CodePudding user response:
Here is a simple approach if you could box all primitive type of 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}