FasterXML / jackson-module-jsonSchema

Module for generating JSON Schema (v3) definitions from POJOs
370 stars 136 forks source link

Cannot deserialize 'format' field #85

Closed hgwood closed 9 years ago

hgwood commented 9 years ago

Format values defined by the spec (date, date-time...) cannot be deserialized into the com.fasterxml.jackson.databind.jsonFormatVisitors.JsonValueFormat type because this enum doesn't provide any means to create instances of it from those values. This type only accepts values such DATE, DATE_TIME etc. However the enum provides a toString that prints the correct values. Very confusing error message ensues:

Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: 
Can not construct instance of com.fasterxml.jackson.databind.jsonFormatVisitors.JsonValueFormat 
from String value 'date': value not one of declared Enum instance names: 
[date-time, date, time, utc-millisec, regex, color, style, phone, uri, email, ip-address, ipv6, host-name]

I don't know if this is an issue with this project, or jackson-databind (which is where the enum is defined).

cowtowncoder commented 9 years ago

Which version is this with? (2.6.3 was just released)

hgwood commented 9 years ago

Sorry, forgot to mention that. Indeed I'm not up-to-date as I'm using 2.4.4. I'll try it with the new version and come back to you.

hgwood commented 9 years ago

I confirm this is still happening with 2.6.3, but with a slightly less confusing error message. Here's a test case:

String serializedSchema = "{\"type\": \"string\", \"format\": \"date\"}";
JsonSchema schema = new ObjectMapper().readValue(serializedSchema, JsonSchema.class);
assertEquals(JsonValueFormat.DATE, schema.asValueSchemaSchema().getFormat());

Result:


com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of com.fasterxml.jackson.databind.jsonFormatVisitors.JsonValueFormat from String value 'date': value not one of declared Enum instance names: [HOST_NAME, COLOR, REGEX, URI, TIME, PHONE, STYLE, EMAIL, DATE_TIME, UTC_MILLISEC, IPV6, DATE, IP_ADDRESS]
 at [Source: {"type": "string", "format": "date"}; line: 1, column: 18] (through reference chain: com.fasterxml.jackson.module.jsonSchema.types.StringSchema["format"])
    at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:55)
    at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:907)
    at com.fasterxml.jackson.databind.deser.std.EnumDeserializer._deserializeAltString(EnumDeserializer.java:130)
    at com.fasterxml.jackson.databind.deser.std.EnumDeserializer.deserialize(EnumDeserializer.java:84)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:161)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:136)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:122)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:93)
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:131)
    at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:42)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2726)
    ...
cowtowncoder commented 9 years ago

I think this area has actually been changed on master (for 2.7.0-SNAPSHOT), but I forget which issue or PR it was. Problem with possible fix for earlier versions is that I think they also serialize schema instances using upper-case constants, which while wrong, will actually successfully deserialize. Changing serialization format along is a behavior change that could cause issues for existing usage, which is why fix in patch release would be risky.

hgwood commented 9 years ago

Is it not possible to support both uppercase-with-underscore (current behavior) and lowercase-with-hyphens (correct behavior)?

cowtowncoder commented 9 years ago

@hgwood sounds doable. PRs welcome.

hgwood commented 9 years ago

I'd be willing to make the change. Would you agree that the best way to go about this is to add a @JsonCreator to the enum? The PR would be against the jackson-databind project.

cowtowncoder commented 9 years ago

That might be the best way yes.

hgwood commented 9 years ago

The test case passes on jackson-databind/master (2.7.0-SNAPSHOT, 4950f446876b8de05c200cd98019bdf1f527d465) so it seems the issue is already fixed. Thanks for your help.