3

I am trying to set null values to database of empty values from JSON payload. This problem caused beacause I have unique constraints on social entity fields. I have request DTO that looks like:

@Value
@With
@Builder
@Jacksonized
public class AccountCreateRequest {

  @NotBlank
  String firstName;

  String phone;

  @Password
  @NotBlank
  String password;

  @Email(message = "Email is not valid.")
  @NotBlank
  String email;

  @NotBlank
  String role;

  SocialDto social;

}

Nested social DTO looks like

@Value
@Builder
@Jacksonized
public class SocialDto {
  @JsonInclude(JsonInclude.Include.NON_EMPTY)
  String telegramId;

  @JsonInclude(JsonInclude.Include.NON_EMPTY)
  String linkedinLink;

  @JsonInclude(JsonInclude.Include.NON_EMPTY)
  String githubLink;
}

Json example:

{

...fields...,
social: {
   telegramId: "",
   githubLink: "",
   ...
  }
}

This JSON object is deserialized with social empty strings and doesn't ignore that values. Moving annotation to the class level - didn't help for me.

How could I fix this problem?

andrew17
  • 851
  • 2
  • 10
  • 25

1 Answers1

0

@JsonInclude(JsonInclude.Include.NON_EMPTY) does not work for the intended purpose of treating empty strings as null on object deserialization. This annotation is for including fields in Object to JSON serialization.

You need to add a custom Deserializer like so: How to deserialize a blank JSON string value to null for java.lang.String?

In order to combine this with @Jacksonized, which already registers a @JsonDeserialize(using = x.class) on the class level, you can do the following:

public class JsonStringDeserializer extends JsonDeserializer<String> {

    @Override
    public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        JsonNode node = jsonParser.readValueAsTree();
        String nodeText = node.asText();
        // todo: isBlank or isEmpty depending on your needs
        if (nodeText.isBlank()) {
            return null;
        }
        return nodeText;
    }
}

and parse the JSON object with the following code:

SimpleModule stringModule = new SimpleModule();
stringModule.addDeserializer(String.class, new JsonStringDeserializer());
ObjectMapper jsonObjectMapper = new ObjectMapper();
jsonObjectMapper.registerModule(stringModule);
jsonObjectMapper.readValue(input, modelClass);

Or you can add @JsonDeserialize(using = JsonStringDeserializer.class) on every String field that needs it if you don't control the ObjectMapper.

slindenau
  • 1,091
  • 2
  • 11
  • 18