Jackson ConstructorProperties ignora propiedades nombres

yanefedor :

Estoy muy confundido cómo Jackson (2.9.6 versión) ObjectMappertrabaja con @ConstructorPropertiesanotación.

Parece que los nombres de los ignorados asignador de propiedad que están presentes en un @ConstructorPropertiesmétodo de valor de anotación.

Lo que es más interesante, - asignador funciona correctamente, independientemente de los nombres de propiedades.

Lo que estoy hablando?

Consideremos XmlMapper personalizado:

private static final ObjectMapper XML_MAPPER = new XmlMapper()
            .setAnnotationIntrospector(
                    AnnotationIntrospector.pair(
                            new JaxbAnnotationIntrospector(),
                            new JacksonAnnotationIntrospector()
                    )
            )
            .registerModule(new JavaTimeModule())
            .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
            .setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE);

y transferencia sencilla de datos de objetos (DTO):

    @XmlRootElement(name = "person")
    @XmlAccessorType(XmlAccessType.NONE)
    static class Person {
        @XmlAttribute
        final int age;

        @XmlAttribute
        final String name;

        @XmlAttribute
        final LocalDate dateOfBirth;

        @ConstructorProperties({"age","name","dateOfBirth"})
        public Person(int age, String name, LocalDate dateOfBirth) {
            this.age = age;
            this.name = name;
            this.dateOfBirth = dateOfBirth;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "age=" + age +
                    ", name='" + name + '\'' +
                    ", dateOfBirth=" + dateOfBirth +
                    '}';
        }
    }

Creé prueba para reproducir el problema:

@Test
@DisplayName("Check xml deseralization for Person class")
void deserialization() throws IOException {
    String xml = "<person age=\"26\" name=\"Fred\" date-of-birth=\"1991-11-07\"/>";
    Person person = XML_MAPPER.readValue(xml, Person.class);
    Assertions.assertEquals("Person{age=26, name='Fred', dateOfBirth=1991-11-07}", person.toString());
}

Es extraño para mí por qué se pasa la prueba, independientemente de @ConstructorPropertiesanotación. La prueba se ha superado con la anotación

        @ConstructorProperties({"a","b","c"})
        public Person(int age, String name, LocalDate dateOfBirth) {
            this.age = age;
            this.name = name;
            this.dateOfBirth = dateOfBirth;
        }

Es una magia? Cómo Jackson procesa esta anotación? Lo que es un equivalente en anotaciones a Jackson ConstructorProperties?

Teppic:

Se pasa porque el JaxbAnnotationIntrospectorpuede determinar los nombres de las propiedades de las @XmlAttributeanotaciones.

El documento sobre AnnotationIntrospectorPairdice:

Clase auxiliar que permite el usar 2 introspectors tal que uno introspector actúa como el principal de usar; y segundo ona como un fallback utiliza si la principal no ofrece resultados concluyentes, o útil para un método.

El JacksonAnnotationIntrospector(que comprende la @ConstructorPropertiesanotación) no se utiliza en absoluto.

Si se quita toda la JAXB anotaciones de la prueba sólo pasará cuando los nombres correctos se especifican en @ConstructorProperties.

Si desea hacerlo "la forma en Jackson", a continuación, quitar las anotaciones JAXB y el JaxbAnnotationIntrospectorcompleto (apenas caer la llamada a setAnnotationIntrospector, el asignador utilizará por defecto el JacksonAnnotationIntrospector).

Deserialización va a trabajar, pero vas a tener que agregar algunas anotaciones nativos Jackson si se quiere lograr el mismo forma serializada:

@JacksonXmlRootElement(localName = "person")
static class Person {
    @JacksonXmlProperty(isAttribute = true)
    final int age;

    @JacksonXmlProperty(isAttribute = true)
    final String name;

    @JacksonXmlProperty(isAttribute = true)
    final LocalDate dateOfBirth;

    @ConstructorProperties({"age", "name", "dateOfBirth"})
    public Person(int age, String name, LocalDate dateOfBirth) {
        this.age = age;
        this.name = name;
        this.dateOfBirth = dateOfBirth;
    }

    //...

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=218773&siteId=1
Recomendado
Clasificación