49

I am trying to map some JSON objects to Java objects with Jackson. Some of the fields in the JSON object are mandatory(which I can mark with @NotNull) and some are optional.

After the mapping with Jackson, all the fields that are not set in the JSON object will have a null value in Java. Is there a similar annotation to @NotNull that can tell Jackson to set a default value to a Java class member, in case it is null?

Edit: To make the question more clear here is some code example.

The Java object:

class JavaObject {
    @NotNull
    public String notNullMember;

    @DefaultValue("Value")
    public String optionalMember;
}

The JSON object can be either:

{
    "notNullMember" : "notNull"
}

or:

{
    "notNullMember" : "notNull",
    "optionalMember" : "optional"
}

The @DefaultValue annotations is just to show what I am asking. It's not a real annotation. If the JSON object is like in the first example I want the value of the optionalMember to be "Value" and not null. Is there an annotation that does such a thing?

58

There is no annotation to set default value.
You can set default value only on java class level:

public class JavaObject 
{
    public String notNullMember;

    public String optionalMember = "Value";
}
  • 26
    This gives a default value if there is no json for the optionalMember. If there is json setting it to "null", it will be null, not "Value" – Lee Meador Apr 25 '16 at 16:00
  • 1
    Added an answer showing how to save Value in case of null – Sergey Voytovich Mar 17 '17 at 15:57
  • 1
    Also, if the class have an AllArgsConstructor, the default value will be erased to null See stackoverflow.com/q/48725922/9640261 – NayoR Nov 22 '18 at 11:05
14

Only one proposed solution keeps the default-value when some-value:null was set explicitly (POJO readability is lost there and it's clumsy)

Here's how one can keep the default-value and never set it to null

@JsonProperty("some-value")
public String someValue = "default-value";

@JsonSetter("some-value")
public void setSomeValue(String s) {
    if (s != null) { 
        someValue = s; 
    }
}
4

Looks like the solution is to set the value of the properties inside the default constructor. So in this case the java class is:

class JavaObject {

    public JavaObject() {

        optionalMember = "Value";
    }

    @NotNull
    public String notNullMember;

    public String optionalMember;
}

After the mapping with Jackson, if the optionalMember is missing from the JSON its value in the Java class is "Value".

However, I am still interested to know if there is a solution with annotations and without the default constructor.

  • 4
    But if the JSON has value null, the optionalMember will end up as null. That may be what is wanted or not. – Lee Meador Apr 25 '16 at 16:01
  • This is the same as just setting the default value on a field. Doesn't solve the problem. – Innokenty Sep 26 '18 at 8:26
2

Make the member private and add a setter/getter pair. In your setter, if null, then set default value instead. Additionally, I have shown the snippet with the getter also returning a default when internal value is null.

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;
}
  • Setter set non-null value, so getter value will go in if statement each time it is called if and only if notNullMember is never set – NayoR Nov 22 '18 at 10:23
0

I had a similar problem, but in my case the default value was in database. Below is the solution for that:

 @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;
 }

Then in SomeDtoJsonDeserializer use ObjectMapper to deserialize the json and set default value if your field/object is null.

0

You can create your own JsonDeserializer and annotate that property with @JsonDeserialize(as = DefaultZero.class)

f.e. for BigDecimal default ZERO:

public static class DefaultZero extends JsonDeserializer { private final JsonDeserializer delegate;

    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;
 }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.