swagger-api / swagger-core

Examples and server integrations for generating the Swagger API Specification, which enables easy access to your REST API
http://swagger.io
Apache License 2.0
7.38k stars 2.18k forks source link

Reading a JSON schema which has a number with minimum/maximum containing scientific notation leads to exception #4754

Open JDUNNIN opened 6 days ago

JDUNNIN commented 6 days ago

Hello, we're hitting an error when trying to read a JSON schema which has a number property with minimum/maximum set to 9.999999999999999999999999999999999E6144 into a Model.class. We are using implementation group: 'io.swagger', name: 'swagger-core', version: '1.6.14' with Java 11, but hit similar issues at 8 or 17.

The JSON schema example is:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "properties": {
        "exampleNumber": {
            "type": "number",
            "minimum": -9.999999999999999999999999999999999E6144,
            "maximum": 9.999999999999999999999999999999999E6144,
            "description": "Nullable DECFLOAT(34)"
        }
    },
    "required": [
        "exampleNumber"
    ],
    "description": "Sample JSON schema"
}

The code we use is:

import io.swagger.models.Model;
import io.swagger.util.Json;

...

        Model retVal = null;
        File schemaFile = new File("requestSchema.json");
        System.out.println(schemaFile.getAbsolutePath());
        if (schemaFile.exists()) {
            Object readAsObject = Json.mapper().readValue(schemaFile, Object.class);
            System.out.println(readAsObject); // prints: {$schema=http://json-schema.org/draft-04/schema#, type=object, properties={exampleNumber={type=number, minimum=-Infinity, maximum=Infinity, description=Nullable DECFLOAT(34)}}, required=[exampleNumber], description=Sample JSON schema}
            retVal = Json.mapper().readValue(schemaFile, Model.class); // exception thrown here
        }

When this runs we get exception:

Exception in thread "main" java.lang.IllegalArgumentException: Character " is neither a decimal digit number, decimal point, nor "e" notation exponential mark. (through reference chain: io.swagger.models.ModelImpl["properties"]->java.util.LinkedHashMap["exampleNumber"])
        at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4624)
        at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:4555)
        at io.swagger.util.ModelDeserializer.deserialize(ModelDeserializer.java:63)
        at io.swagger.util.ModelDeserializer.deserialize(ModelDeserializer.java:20)
        at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
        at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4905)
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3713)
        at dbcs.App.testBigDec(App.java:30)
        at dbcs.App.main(App.java:20)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Character " is neither a decimal digit number, decimal point, nor "e" notation exponential mark. (through reference chain: io.swagger.models.ModelImpl["properties"]->java.util.LinkedHashMap["exampleNumber"])
        at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:402)
        at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:361)
        at com.fasterxml.jackson.databind.deser.std.ContainerDeserializerBase.wrapAndThrow(ContainerDeserializerBase.java:190)
        at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringKeyMap(MapDeserializer.java:638)
        at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:449)
        at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:32)
        at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:310)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
        at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4619)
        ... 8 more
Caused by: java.lang.NumberFormatException: Character " is neither a decimal digit number, decimal point, nor "e" notation exponential mark.
        at java.base/java.math.BigDecimal.<init>(BigDecimal.java:522)
        at java.base/java.math.BigDecimal.<init>(BigDecimal.java:405)
        at java.base/java.math.BigDecimal.<init>(BigDecimal.java:838)
        at io.swagger.util.PropertyDeserializer.getBigDecimal(PropertyDeserializer.java:61)
        at io.swagger.util.PropertyDeserializer.argsFromNode(PropertyDeserializer.java:193)
        at io.swagger.util.PropertyDeserializer.propertyFromNode(PropertyDeserializer.java:347)
        at io.swagger.util.PropertyDeserializer.deserialize(PropertyDeserializer.java:139)
        at io.swagger.util.PropertyDeserializer.deserialize(PropertyDeserializer.java:41)
        at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringKeyMap(MapDeserializer.java:623)
        ... 14 more

Do you know if we are hitting a limitation of swagger-core in this scenario? Should we be configuring some additional options on the Json.mapper() to handle this scenario?

JDUNNIN commented 2 hours ago

Found that Json.mapper().configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true).readValue(schemaFile, Model.class); can be used which does not throw an exception.