J'essaie de mapper des objets JSON en objets Java avec Jackson. Certains champs de l’objet JSON sont obligatoires (que je peux marquer avec @NotNull
) et d’autres sont facultatifs.
Après le mappage avec Jackson, tous les champs non définis dans l'objet JSON auront une valeur NULL en Java. Existe-t-il une annotation similaire à @NotNull
qui peut indiquer à Jackson de définir une valeur par défaut sur un membre de la classe Java, au cas où elle serait nulle?
Edit: Pour clarifier la question, voici un exemple de code.
L'objet Java:
class JavaObject {
@NotNull
public String notNullMember;
@DefaultValue("Value")
public String optionalMember;
}
L'objet JSON peut être soit:
{
"notNullMember" : "notNull"
}
ou:
{
"notNullMember" : "notNull",
"optionalMember" : "optional"
}
Les annotations @DefaultValue
sont juste pour montrer ce que je demande. Ce n'est pas une vraie annotation. Si l'objet JSON est comme dans le premier exemple, je souhaite que la valeur de la variable optionalMember
soit "Value"
et non null
. Y at-il une annotation qui fait une telle chose?
Il n'y a pas d'annotation pour définir la valeur par défaut.
Vous pouvez définir la valeur par défaut uniquement au niveau de la classe Java:
public class JavaObject
{
public String notNullMember;
public String optionalMember = "Value";
}
Une seule solution proposée conserve le default-value
lorsque some-value:null
a été défini explicitement (la lisibilité du POJO y est perdue et elle est maladroite)
Voici comment conserver le default-value
et ne jamais le régler sur null
@JsonProperty("some-value")
public String someValue = "default-value";
@JsonSetter("some-value")
public void setSomeValue(String s) {
if (s != null) {
someValue = s;
}
}
On dirait que la solution consiste à définir la valeur des propriétés à l'intérieur du constructeur par défaut. Donc, dans ce cas, la classe Java est:
class JavaObject {
public JavaObject() {
optionalMember = "Value";
}
@NotNull
public String notNullMember;
public String optionalMember;
}
Après le mappage avec Jackson, si la variable optionalMember
est absente du JSON, sa valeur dans la classe Java est "Value"
.
Cependant, je suis toujours intéressé de savoir s'il existe une solution avec des annotations et sans le constructeur par défaut.
Rendre le membre privé et ajouter une paire setter/getter . Dans votre setter, si null, définissez la valeur par défaut à la place de .. .
class JavaObject {
private static final String DEFAULT="Default Value";
public JavaObject() {
}
@NotNull
private String notNullMember;
public void setNotNullMember(String value){
if (value==null) { notNullMember=DEFAULT; return; }
notNullMember=value;
return;
}
public String getNotNullMember(){
if (notNullMember==null) { return DEFAULT;}
return notNullMember;
}
public String optionalMember;
}
Vous pouvez créer votre propre JsonDeserializer et annoter cette propriété avec @JsonDeserialize(as = DefaultZero.class)
f.e. pour BigDecimal par défaut ZERO:
classe statique publique DefaultZero étend JsonDeserializer {délégué final privé JsonDeserializer;
public DefaultZero(JsonDeserializer<BigDecimal> delegate) {
this.delegate = delegate;
}
@Override
public BigDecimal deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
return jsonParser.getDecimalValue();
}
@Override
public BigDecimal getNullValue(DeserializationContext ctxt) throws JsonMappingException {
return BigDecimal.ZERO;
}
}
f.e.
class Sth {
@JsonDeserialize(as = DefaultZero.class)
BigDecimal property;
}
J'ai eu un problème similaire, mais dans mon cas, la valeur par défaut était dans la base de données. Voici la solution pour cela:
@Configuration
public class AppConfiguration {
@Autowired
private AppConfigDao appConfigDao;
@Bean
public Jackson2ObjectMapperBuilder builder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
.deserializerByType(SomeDto.class,
new SomeDtoJsonDeserializer(appConfigDao.findDefaultValue()));
return builder;
}
Ensuite, dans SomeDtoJsonDeserializer
, utilisez ObjectMapper
pour désérialiser le json et définir la valeur par défaut si votre champ/objet est null.