FasterXML/jackson-modules-base

JaxbAnnotationModule/JaxbAnnotationIntrospector java time support missing

jasonhjia opened this issue · 3 comments

run into issue with OffsetJavaDateTime while generate JSON schema from existing jaxb classes.

For example, the jaxb class is defined as following

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "Bean", propOrder = {
            "name",
            "exceptionDateTime"
    })
    public static class Bean {
        @XmlElement(name = "name")
        public String name;
        @XmlElement(name = "ExceptionDateTime", required = true, type = String.class)
        @XmlJavaTypeAdapter(OffsetDateTimeXmlAdapter.class)
        @XmlSchemaType(name = "dateTime")
        public OffsetDateTime exceptionDateTime;
    }

It generates the following json schema:

{
  "type" : "object",
  "id" : "urn:jsonschema:test:JacksonSchemaTest:Bean",
  "properties" : {
    "name" : {
      "type" : "string"
    },
    "ExceptionDateTime" : {
      "type" : "string",
      "required" : true
    }
  }
}

what I expect is to have "format" : "date-time" in ExceptionDateTime.

Here's the code I used to test this:

package test;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
import com.fasterxml.jackson.module.jsonSchema.factories.SchemaFactoryWrapper;
import io.github.threetenjaxb.core.OffsetDateTimeXmlAdapter;

import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.time.OffsetDateTime;

public class JacksonSchemaTest {
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "Bean", propOrder = {
            "name",
            "exceptionDateTime"
    })
    public static class Bean {
        @XmlElement(name = "name")
        public String name;
        @XmlElement(name = "ExceptionDateTime", required = true, type = String.class)
        @XmlJavaTypeAdapter(OffsetDateTimeXmlAdapter.class)
        @XmlSchemaType(name = "dateTime")
        public OffsetDateTime exceptionDateTime;
    }

    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        mapper.registerModule(new JavaTimeModule());
        mapper.registerModule(new JaxbAnnotationModule());
        SchemaFactoryWrapper visitor = new SchemaFactoryWrapper();

        mapper.acceptJsonFormatVisitor(mapper.constructType(Bean.class), visitor);
        JsonSchema jsonSchema = visitor.finalSchema();
        System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema));
    }
}

Note that if I register JavaTimeModule only, then I got the correct format element in JSON schema, but it misses the "required" : true

The jackson lib version is 2.13.0

Looks like Adapter annotation manages to change effective type to String, which then produces schema you see.
So I don't think it is specific date/time type but converter that is the problem here.
This does not really help much other than suggest that almost any other type would exhibit similar problem with similar annotations.

Oh. Actually... it's probably type=String.class in @XmlElement that is problematic.
Is that actually needed? If not, I'd consider removing it and seeing if that resolves the problem.

yeah, I figure it out the same. However, the jaxb classes are generated by xjc from wsdl, so change it manually really is not an option.
I guess this is mainly due to the java type and/or the @XMLSchemaType is ignored by JaxbAnnotationIntrospector

I don't think @XMLSchemaType could be used in here in the sense that it would related to XML Schema information that Jackson cannot really use for anything. It is possible that type from @XmlElement is used in incorrect way.

You might be able to sub-class JaxbAnnotationIntrospector (or whatever the name is), and override relevant method to discard that bit of information.