Is there a way to make #JsonIgnoreProperties target nested attributes?
Something like the code below:
public class ParentObject() {
#JsonIgnoreProperties({ "subAttributeA.subAttributeB.subAttributeC" })
private ChildObject attribute;
}
In this example, I want that subAttributeC is not included in the serialization of a ParentObject - but this same subAttributeC still need to be serializable in other scenarios.
If not possible with annotations, how to achieve this?
One possible way is to use #JsonSerialize with a custom serializer. This operates on a low abstraction level and you basically have to specify how to serialize every single attribute. There's an example here that uses a flat object, but given that JsonGenerator has methods like writeObject etc., I'm sure this can be used for a hierarchical structure, too.
If jackson is configured to not serialize null attributes:
objectMapper.setSerializationInclusion(Include.NON_NULL);
Then a simpler workaround is to set the unwanted attribute as null before returning it.
Related
I'm using Java jackson for dynamic serialization and deserialization to/from json.
I want to have a custom annotation #JsonDebug, which will basically turn on/off the serialization of
field etc. depending on a static variable debugMode. The idea is that if an enum key is tagged with the annotation,
it shouldn't be useable while serialization/deserialization process is on.
The problem is that the only way I find doing it is by either implementing custom serializer/deserializer for the enum I want, which is not a general solution or by overriding the existing Enum serialization/deserialization process which is kind of a overkill for a single annotation processing. I tried using AnnotationIntrospector and override behavior of hasIgnoreMarker which is the way it works for fields, but it doesn't ignore enum keys. I thought mixin annotations might be the way to go, but they only work for specified classes with specified field names. I found out that even with ignore annotations on keys, they still serialize/deserialize to/from json.
.
I have some classes containing integer IDs, something like this:
class MyClass {
int myId;
// Other fields
}
I need a way to use a custom serializer only in certain cases (so that I cannot use #JsonAdapter) and of course I cannot generically use this serializer for all the integer values, because sometimes I want a sort of transformation of my ID (i.e. this is a web server response and I want to mask my ids so that they cannot be reused).
The full data model is quite complex and deep, and I annotated all the ID fields (even when they are collections) with a custom annotation #MyId. The point is that I don't find a valid way to say to a Gson instance "please, use this serializer for fields annotated with #MyId.
Do you have any ideas?
I found that jackson comes equipped with a UUID serizlizer/deserializer that can be used like this:
#Data
#NoArgsConstructor
public class MyClass {
#JsonSerialize(using=UUIDSerializer.class)
#JsonDeserialize(using=UUDIDeserializer.class)
private UUID myUUID;
}
And then using ObjectMapper on MyClass will correctly serialize/deserialize the myUUID field.
However, my class has a set of UUIDs that I want to serialize. I tried annotating the field the same way as above, but it complains that Set cannot be converted to UUID (as I half expected).
I know I can create my own serializer/deserializers by extending JsonSerializer/JsonDeserializer, but this feels hacky. Is there another solution I can use? I also don't have the option to configure the ObjectMapper with my classes, since I don't have access to the ObjectMapper. I am using Amazon SWF and it automatically uses Jackson.
Jackson should automatically use UUID serializers, deserializers, so your annotations should not be necessary.
But as to annotation usage, as suggested, (de)serializer for content (instead of value itself!) does need to use contentUsing property of the annotation -- otherwise Jackson will try to apply given (de)serializer directly for the value, with reported mismatch,
I want to serialize an object using java jackson.
I want to serialize it once in a short version
and second in a full version.
I have added a #JsonIgnore annotation over the non-mandatory fields.
But how can I tell jackson to serialize all fields including #JsonIgnore when desired?
It is possible to ignore #JsonIgnore. I can think of 2 approaches:
Extend JacksonAnnotationIntrospector, over hasIgnoreMarker(...) method (I think that's the name -- can check javadocs)
Add #JsonIgnore(false) annotation override using "mix-in annotations": false means "do not ignore", and is explicitly allowed to be used (default value is true) for such overrides.
However: a better way would be to use JSON Views, or JSON filters.
Ideally, it would look much like this:
List<String> props = objectMapper.getKnownProperties(MyPojo.class);
Alas, there is no such method. An approach that would generally work is to explicitly set Include.ALWAYS as the ObjectMapper's default, instantiate an instance of the class reflectively, convert it to a map, and examine the keyset. However, classes can still override the ObjectMapper's include behavior given annotations.
Is there a more elegant approach? At the very least, is there a way to override class annotations using the object mapper?
Edit:
Just to clarify, these pojos/javabeans/DTOs are designed for use with Jackson and are already rigged with annotations to result in specific serialization behavior. It just so happens that I need to dynamically know what I might end up with up-front, ideally without duplicating the information already available to jackson. That said, if another framework offers this functionality, I'd be curious to know. :)
With Jackson, you can introspect a class and get the available JSON properties using:
// 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();
If you have #JsonIgnoreProperties class level annotations, check this answer.
Depending on your exact needs, JsonFilter could also work (f.ex see http://www.cowtowncoder.com/blog/archives/2011/09/entry_461.html).
And for more advanced cases, BeanSerializerModifier does give you access to actual list of BeanPropertyWriters, which represent individual properties POJO has. From that, you could write a wrapper that enables/disables output dynamically.
Or perhaps you can even combine approaches: modifier to get list of possible property names; then FilterProvider to dynamically add filter. Benefit of this would be that it is a very efficient way of implementing filtering.
It's possible to ignore all annotations by using a dummy AnnotationIntrospector:
objectMapper.setAnnotationIntrospector(new AnnotationIntrospector(){
#Override public Version version() {
return Version.unknownVersion();
}
});
Perhaps you could use Jackson's JSON Schema module to generate a schema for a class, then inspect the schema.