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,
Related
Previously in version 3 of Spring Data Elasticsearch, the Jackson mapper was used by default, but could be overridden to use the Metamodel object mapper, as documented here:
https://docs.spring.io/spring-data/elasticsearch/docs/3.2.0.RC1/reference/html/#elasticsearch.mapping.meta-model
I understand the Jackson mapper has been removed in version 4 and replaced with the Metamodel object mapper, as documented here:
https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.mapping
But it appears the ability to override the object mapper was removed as well. Is there indeed no way to configure the Elasticsearch global object mapper to use Jackson (or any other mapper) again? It seems like a shame to lose the flexibility that option provided.
No. The MappingConverter is not only used and needed for converting an entity to and from JSON, but also for converting and mapping fieldnames, dateformats and other stuff for example when CriteriaQuerys are created or when search resukts like highlights are processed. There are man places in Spring Data Elasticsearch where the mapping information for an entity is needed and Jackson cannot be used there.
So in versions before 4.0 it was necessary to customize Jackson with jackson-annotations on the entity and the other stuff with different annotations, this has been consolidated.
What functionality do you need that the MappingConverter (implementation of the meta model mapper) does not offer in combination with custom converters?
Edit 05.12.2020:
valid point from the comments: It should be possible to define a FieldNamingStrategy for an entity. I created an issue for that.
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.
.
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.
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.