1

This is class against which we are going to map the incoming request

@Getter
@Setter
public class FooRequest {
    @Size(max = 255, message = "{error.foo.name.size}")
    private String name;

    @Digits(integer = 15, fraction = 0, message = "{error.foo.fooId.size}")
    private Long fooId;

    @Digits(integer = 15, fraction = 0, message = "{error.foo.barId.size}")
    private Long barId;
    }

I have used javax.validation.constraints.* like above. If we send request like

{
    "name": "Test",
    "fooId": "0001234567",
    "barId": "0003456789"
    }

Then It works fine and we are able to save the results in the database but if we send it like:

{
    "name": "Test",
    "fooId": 0001234567,
    "barId": 0003456789
    }

Then we are getting 400 Bad Request. I am not getting it what wrong am I doing, I just want to ensure that user sends digits, having length between 1-15 and wants to map it against the Long variable. Is it because of fraction or because all these values are starting with 0?

implosivesilence
  • 536
  • 10
  • 24

1 Answers1

2

The second JSON is not a valid json because of the leading zeroes.

Background

Spring uses Jackson library for JSON interactions.

The Jackson's ObjectMapper by default throws if you try to parse the second JSON:

public class Main {
    public static void main(String[] args) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.readValue("{\"name\": \"Test\", \"fooId\": 0001234567, \"barId\": 0003456789}", FooRequest.class);
    }
}

The exception is:

Exception in thread "main" com.fasterxml.jackson.core.JsonParseException: Invalid numeric value: Leading zeroes not allowed
 at [Source: (String)"{"name": "Test", "fooId": 0001234567, "barId": 0003456789}"; line: 1, column: 28]

One can allow leading zeroes via the JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS:

public class Main {
    public static void main(String[] args) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);
        FooRequest fooRequest = objectMapper.readValue("{\"name\": \"Test\", \"fooId\": 0001234567, \"barId\": 0003456789}", FooRequest.class);

        System.out.println(fooRequest.getBarId());
    }
}

Or in spring via the Spring Boot's application.properties:

spring.jackson.parser.allow-numeric-leading-zeros=true

then, the second JSON will be parsed successfully.

Why does it work with the first JSON?

Because by default Jackson's MapperFeature.ALLOW_COERCION_OF_SCALARS is turned on.

From its javadoc:

When feature is enabled, conversions from JSON String are allowed, as long as textual value matches (for example, String "true" is allowed as equivalent of JSON boolean token true; or String "1.0" for double).


because all these values are starting with 0?

So it turns out that, yes, but for a slightly different reason

Denis Zavedeev
  • 7,627
  • 4
  • 32
  • 53