In my current project the names of the model class fields are German. The fields are all annotated with #JsonProperty for the English translation of the names. E.g. #JsonProperty(value = "operation"). Is there a way in the configuration that the mapping of the fields is done using the JsonProperty annotation?
Example:
public class Auftrag {
#JsonProperty(value = "orderType")
private String auftragsart;
...
}
public class OrderDto {
private String orderType;
}
MapStruct uses the Java Bean convention to detect the properties. This means that it looks in the getters and setters.
Out-of-the-box you cannot use the #JsonProperty. However, you can create your own AccessorNamingStrategy that will provide the properties based on #JsonProperty. The AccessorNamingStrategy gives you access to the Abstract syntax tree, which means you can look for fields in types, check their annotations and check their values.
Keep in mind that MapStruct will only ask to get the property for a method, so you would need to get the property name, then find the field in the type, then look for the #JsonProperty annotation and its value.
You can read more about the AccessorNamingStrategy here in the documentation.
Related
Due to the fact that I'm using an abstract class, I get such error:
org.springframework.data.mapping.MappingException: Ambiguous field mapping detected!
Both private final com.life.book.domain.event.EventType com.life.book.domain.command.ObjectCommand.eventType
and private final com.life.book.domain.event.EventType com.life.book.domain.command.UpdateObjectCommand.eventType
map to the same field name eventType! Disambiguate using #Field annotation!
My classes:
abstract class ObjectCommand(
open var eventType: EventType?
)
#Document(collection = "COMMAND")
data class UpdateObjectCommand(
val description: String?,
override var eventType: EventType?
) : ObjectCommand(eventType)
enum class EventType {
CREATED, UPDATED
}
The solution might be to use a different name instead of the eventType name in the UpdateObjectCommand class. But then the database will have two fields with the same purpose. Maybe there is another way?
There is Disambiguate using #Field annotation in the description of the error, but I don't understand how to use it.
It's been a sec since I have delt with what looks like Mongo DB and Spring Boot (I could be off base here). The #Field annotation is applied to fields in your class that have the #Document annotation.
You can add information to the #Field annotation like the serialized name of the field, or if its written when null. #Field in most cases does not need to be applied to a field unless you are dealing with enums. Mongo does not know how to store an enum, so you must add the #Field annotation to specify that it needs to be stored as a string.
https://blog.tericcabrel.com/using-mongodb-with-spring-boot-project-part-1/
From tericcabrel.com:
#Field is used to enhance the property by changing the type; like our case, MongoDB doesn't support Enum, so we need to tell Mongo to store this property's value as a string. When retrieving the data from the collection, the value will be returned back as an Enum. You can also provide a different name for the property in MongoDB.
If I pass a JSON like
`{
"entity":{
"name":"xyz",
"age":21
}
}`
Then , is it compulsory that my POJO should have both "name" and "age" instance variables. I mean, if I have only "name" instance field, will there be any exception while mapping?
If your JSON contains extra fields which are not present in POJO, it will throw an exception. To avoid that you can ignore additional fields using this annotation #JsonIgnoreProperties.
if field names are different, you can define at field getter using #jsonProperty. (for deserialization).
for serialization use annotation on the setter method.
#JsonIgnoreProperties(ignoreUnknown = true)
class Pojo {
private String name;
#jsonProperty("firstName")
public String getName(){
return this.name;
}
}
is it compulsory that my POJO should have both "name" and "age" instance variables
If you mean "have" as in the same names exactly, then no. You can use annotations to rename the values.
If you instead mean the class definition "contains" those values, then also it shouldn't need them. That depends on how you configure ObjectMapper, though. For example, there is an AnyGetter annotation that will allow you to collect "extra" JSON values. Therefore, it makes sense that mandatory fields are not required.
Does naybody knows a way to use Jersey's GET method to return a JSON that returns only some fields of an entity instead of all?
Does anybody know a way to use Jersey's GET method to return a JSON that returns only some fields of an entity instead of all?
E.g. in the following class I want to receive (with POST) values for 'name' and for 'confidential', buy while returning (with GET) I only need 'name' value, not 'confidential'.
#Entity
#Table(name = "a")
#XmlRootElement
#JsonIgnoreProperties({"confifentialInfo"})
public class A extends B implements Serializable {
private String name;
#Basic(optional = false)
private String confifentialInfo;
// more fields, getters and setters
}
If you are using the JAXB approach, you can mark fields with #XmlTransient to omit them. If you are using POJO mapping or want to exclude fields only for some requests, you should construct the JSON with the low level JSON API.
If you are using Jackson, you can use the annotation #JsonIgnore for methods
Marker annotation similar to javax.xml.bind.annotation.XmlTransient
that indicates that the annotated method is to be ignored by
introspection-based serialization and deserialization functionality.
That is, it should not be consider a "getter", "setter" or "creator".
And #JsonIgnoreProperties for properties
Annotation that can be used to either suppress serialization of
properties (during serialization), or ignore processing of JSON
properties read (during deserialization).
In Java, is there a way to change the behaviour of an annotation depending on the type of the annotated field?
I know that annotation presence is supposed to be tested by code. Not the opposite. But the case is rather particular: this is a Jackson 2.0 « inside » annotation which gather a list of annotations. We use it to define the field name (#JsonProperty) and the field serializing policies (#JsonSerialize).
The serialisation policies must be adapted to the annotated field. And, because we are talking of a framework, one unique annotation is far better than two separate ones.
#Retention(RUNTIME)
#JacksonAnnotationsInside.
#JsonProperty("_id")
#JsonSerialize(using=IdSerializer.class)
#JsonDeserialize(using=IdDeserializer.class)
public #interface Id {}
Some cases need to turn the serializers down, that's the point. In the following example, the String must be processed by the de/serializers, ObjectId don't. Both need to be renamed _id by the #JsonProperty.
public class Car {
#Id String id
}
public class Bus {
#Id ObjectId id
}
Any clues?
I'm using MappingJacksonJsonView to serialize to JSON a class, however, I'd like to be able to rename some of the fields from the default name based on the getter name.
This is because I've to output field names like "delete_url" and "delete_type" for jQuery file upload. I'm using #Jsonserialize annotation to hand pick the fields to serialize.
#JsonAutoDetect(getterVisibility = Visibility.NONE)
public interface Picture {
#JsonSerialize
String getName();
#JsonSerialize
String getDelete_url();
...
For instance, I'm forced to call a method getDelete_url(), while I'd like to call it getDeleteUrl(), but still output the key "delete_url" when serializing to JSON.
You should be able to qualify using #JsonProperty.
#JsonAutoDetect(getterVisibility = Visibility.NONE)
public interface Picture {
#JsonSerialize
#JsonProperty("name")
String getName();
#JsonSerialize
#JsonProperty("delete_url")
String getDeleteUrl();
//...
Have you tried using the #JsonProperty annotation?
"Defines name of the logical property, i.e. Json object field name to use for the property: if empty String (which is the default), will use name of the field that is annotated."