I'm writing code that needs to access the list of properties of a class as defined by a Jackson configuration.
For instance, for the following class:
@JsonIgnoreProperties(value = { "intValue" })
public class MyDto {
@JsonProperty("name")
private String stringValue;
private int intValue;
private long longValue;
@JsonIgnore
private boolean booleanValue;
// standard setters and getters are not shown
}
I would get [name,longValue]
because that's the properties that Jackson actually considers when serializing.
I don't think writing a whole piece of code to look for getters/setters and inspect Jackson annotations is the way to go, since that would be reimplementing Jackson.
If I'm able to get a handle on the Jackson ObjectMapper
used for serialization, is there a way to get a list of properties of a Class<?>
or Type
object? (respecting Jackson annotations and config)
I dug a bit into Jackson's implementation, and found the POJOPropertiesCollector
, but I'm not sure about how I can use it from outside Jackson (we're not supposed to do this I believe).
As a last resort, I could create an instance of the class I'm inspecting, serialize it with the ObjectMapper, and then parse the JSON to find property names, but I don't think this is clean either (and it would bring its whole set of probelms: nulls might not be serialized, what happens in the construtor etc.).
Any ideas?
@JsonProperty is used to mark non-standard getter/setter method to be used with respect to json property.
@JsonCreator is used to fine tune the constructor or factory method used in deserialization. We'll be using @JsonProperty as well to achieve the same. In the example below, we are matching an json with different format to our class by defining the required property names.
@JsonIncludeIt is used at serialization time only. It says that if the value of a property (or all properties) in question is equal to a certain value ( null , empty - whatever that means, or a default value) this property is not serialized. Without this annotation, the property value is always serialized.
With Jackson, you can introspect an arbitrary class to get the available JSON properties:
// Construct a Jackson JavaType for your class
JavaType javaType = mapper.getTypeFactory().constructType(MyDto.class);
// Introspect the given type
BeanDescription beanDescription = mapper.getSerializationConfig().introspect(javaType);
// Find properties
List<BeanPropertyDefinition> properties = beanDescription.findProperties();
The BeanPropertyDefinition
list should give you the details you need regarding the JSON properties.
The @JsonIgnoreProperties
class level annotation is not taken into account with the above mentioned approach. But you can use an AnnotationIntrospector
to get the properties ignored on class level:
// Get class level ignored properties
Set<String> ignoredProperties = mapper.getSerializationConfig().getAnnotationIntrospector()
.findPropertyIgnorals(beanDescription.getClassInfo()).getIgnored();
Then filter properties
removing the properties which are present in ignoredProperties
:
// Filter properties removing the class level ignored ones
List<BeanPropertyDefinition> availableProperties = properties.stream()
.filter(property -> !ignoredProperties.contains(property.getName()))
.collect(Collectors.toList());
This approach works even if you have mix-ins defined for your class.
The AnnotationIntrospector#findPropertyIgnorals(Annotated)
method was introduced in Jackson 2.8. The AnnotationIntrospector#findPropertiesToIgnore(Annotated, boolean)
method can be used for older versions (but it's deprecated since Jackson 2.8).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With