Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incoherence between serialized object and generated schema for enum with @JsonValue #128

Open
matthieu-honel-vectaury opened this issue Feb 8, 2018 · 2 comments

Comments

@matthieu-honel-vectaury
Copy link

matthieu-honel-vectaury commented Feb 8, 2018

A class has a field which is an enum.
The enum type is annotated with @JsonFormat(shape = JsonFormat.Shape.NUMBER_INT) so it is serialized as an integer.
The enum type has an int field which is annotated with @JsonValue so this value is used instead of the ordinal of the enum constant.

Expected behavior:
The enum field of an instance of the class is serialized as an integer (number).
The schema generated for the enum field of the class describes an integer type with an enum array containing integers.

Actual behavior:
The enum field of an instance of the class is serialized as an integer (number).
The schema generated for the enum field of the class describes a string type with an enum array containing string.

As a result, trying to validate a serialized instance with the JSON Schema gives an error (test not included in code below).

Test code:

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
import com.fasterxml.jackson.module.jsonSchema.JsonSchemaGenerator;

public class Generator {
    public static void main(String... args) throws JsonProcessingException {
        // instantiate class
        ClassWithEnumField a = new ClassWithEnumField();
        a.numberEnumWithJsonValue = NumberEnumWithJsonValue.VALUE_1;

        // mapper with pretty print feature
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);

        // serialize class instance
        System.out.println("Serialized instance:");
        System.out.println(objectMapper.writeValueAsString(a));

        // generate and serialize schema
        JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(objectMapper);
        JsonSchema jsonSchema = jsonSchemaGenerator.generateSchema(ClassWithEnumField.class);
        System.out.println("Serialized schema:");
        System.out.print(objectMapper.writeValueAsString(jsonSchema));
    }

    static class ClassWithEnumField {
        @JsonProperty("numberEnumWithJsonValue")
        NumberEnumWithJsonValue numberEnumWithJsonValue;
    }

    @JsonFormat(shape = JsonFormat.Shape.NUMBER_INT)
    enum NumberEnumWithJsonValue {
        VALUE_1(1),
        VALUE_2(2);

        @JsonValue
        public final int value;

        NumberEnumWithJsonValue(int value) {
            this.value = value;
        }

    }

}

Output:

Serialized instance:
{
  "numberEnumWithJsonValue" : 1
}
Serialized schema:
{
  "type" : "object",
  "id" : "urn:jsonschema:Generator:ClassWithEnumField",
  "properties" : {
    "numberEnumWithJsonValue" : {
      "type" : "string",
      "enum" : [ "1", "2" ]
    }
  }
}

Expected output:

Serialized instance:
{
  "numberEnumWithJsonValue" : 1
}
Serialized schema:
{
  "type" : "object",
  "id" : "urn:jsonschema:Generator:ClassWithEnumField",
  "properties" : {
    "numberEnumWithJsonValue" : {
      "type" : "integer",
      "enum" : [ 1, 2 ]
    }
  }
}

Using com.fasterxml.jackson.module:jackson-module-jsonSchema:2.9.4 as a gradle dependency.

@bfconsultinginc
Copy link

I am experiencing the same issue. Has there been or will there be any attempt to develop a fix for this? Do you need additional contributors?

I am willing to attempt to correct this, ideally, if you provide direction as to what should be modified so I can make the appropriate changes and issue a pull request.

@cowtowncoder
Copy link
Member

If someone had worked on it, there would be a note here. I don't think anyone is working on this module at this point. It is fair to say this module is an orphan, similar to Scala and Hibernate modules.

As to how to fix that, I do not know details. But the way schema generation works is that JsonSerializer instances for type have method acceptJsonFormatVisitor() which calls methods on visitor object given; and then this module provides visitors that generate schema based on callbacks.
Problem(s) involved may thereby be either on jackson-databind side (EnumSerializer, most likely), or this module, or possibly, both.
And a common challenge is that sometimes information passed by databind is incomplete so fix might require a change to introspection part, which is difficult from backwards compatibility perspective.

I hope above helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants