jackson-module-jsonSchema icon indicating copy to clipboard operation
jackson-module-jsonSchema copied to clipboard

"minimum": 0.0 is not set when @Min(0) is used

Open matlach opened this issue 9 years ago • 9 comments

Consider the following:

public class Person {
    @Min(0)
    private int id;
}

when serialized to json schema, will output:

{
  "type" : "object",
  "id" : "urn:jsonschema:xxx:Person",
  "properties" : {
    "id" : {
      "type" : "integer"
    }
}

instead of:

{
  "type" : "object",
  "id" : "urn:jsonschema:xxx:Person",
  "properties" : {
    "id" : {
      "type" : "integer",
      "minimum" : 0.0
    }
}

everything works fine if we define any other number than 0.

By looking at the ValidationConstraintResolver/AnnotationConstraintResolver, why the minimumValue/maximumValue is always converted to double?

When the type is integer, shoudn't the minimum/maximum value stays to an integer format? When I look at the following documentation: http://spacetelescope.github.io/understanding-json-schema/reference/numeric.html Under range, the integer format is preserved. Should I open different issues for this?

Thank you very much!

matlach avatar Sep 24 '15 12:09 matlach

The problem is in this class: com.fasterxml.jackson.databind.ser.std.NumberSerializers#DoubleSerializer If the value is 0 (or 0.0 because is converted to double) then it will be skipped. This is call there com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanPropertyWriter#serializeAsField

 if (_suppressableValue != null) {
            if (MARKER_FOR_EMPTY == _suppressableValue) {
                if (ser.isEmpty(prov, value)) {
                    return;
                }
            } else if (_suppressableValue.equals(value)) {
                return;
            }
        }

I try to use config and annotation JsonInclude.Include.ALWAYS but without any success.

final ObjectMapper mapper = new ObjectMapper();
mapper.acceptJsonFormatVisitor(dtoClass, entityVisitor);
mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS).writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema);

alaingiller avatar Jun 16 '16 13:06 alaingiller

@alaingiller Global setting is only default, per-property annotation will override it.

Which Jackson version are you using? Jackson 2.6 did consider default primitive values as "empty", but due to user feedback this change was reverted so that all other versions (and both 2.5 and 2.7) only consider "empty" to apply to container types, Optionals and String.

cowtowncoder avatar Jun 16 '16 15:06 cowtowncoder

I'm using jackson-jsonSchema 2.7.3 and also try with 2.7.4 and jackson-databind 2.6.6 The problem is for JSR-303 annotation one should not check if value is "empty". With current implementation @Min(0) cannot work. I also try with @JsonInclude(JsonInclude.Include.ALWAYS) on both class and field but without any success. For json-schema one shouldn't call isEmpty() of com.fasterxml.jackson.databind.ser.std.NumberSerializers#DoubleSerializer

alaingiller avatar Jun 16 '16 18:06 alaingiller

@alaingiller Inclusion is not used for JSR-303 annotation at all. It is only checked when serializing values of POJOs. So for the inclusion settings to take effect here, specific Schema value class has to have inclusion settings that do that. JSON Schema value objects are nothing special from Jackson perspective (nor should they be): they are handled just like any other Java class, based on settings and annotations.

At this point I do not know how to reproduce the problem.

cowtowncoder avatar Jun 16 '16 19:06 cowtowncoder

Very easy to reproduce: Create this pojo:

public class SimplePojo{
    @Min(0)
    private int dontWork;

    @Min(1)
    private int workWell;
/* getter & setter */
}

and then: final SchemaFactoryWrapper entityVisitor = schemaFactoryWrapperClass.newInstance(); final ObjectMapper mapper = new ObjectMapper(); mapper.acceptJsonFormatVisitor(dtoClass, entityVisitor); final JsonSchema jsonSchema = entityVisitor.finalSchema(); System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema));

The generated JsonSchema will be correct for workWell but not for dontWork

alaingiller avatar Jun 16 '16 19:06 alaingiller

Correct in... ?

cowtowncoder avatar Jun 16 '16 19:06 cowtowncoder

Generated json-schema:

{
  "type" : "object",
  "id" : "urn:jsonschema:SimplePojo",
  "properties" : {
    "dontWork" : {
      "type" : "integer"
    },
    "workWell" : {
      "type" : "integer",
      "minimum" : 1.0
    }
}

Correct in case property "dontWork" has "minimum": 0.0 but only "workWell" has it.

alaingiller avatar Jun 16 '16 20:06 alaingiller

@alaingiller You can have problem with "java object -> json" writer. I debug it and check that at runtime JsonSchema object has "minimum" property with value 0.0. And if you will write test and check, then you make sure that everything is ok.

ivan-osipov avatar Jul 28 '16 10:07 ivan-osipov

@ivan-osipov : So you say that you run my little exemple and you didn't get the same result as me? With the current version, @Min(0) on an Integer has not the same effect (skipped by the schema-generation) as @Min(1) and it's definitely a BUG

alaingiller avatar Jul 28 '16 12:07 alaingiller