javafasterxml

How do I remove a wrapper for an object when using XmlWrapper?


The XML output contains the wrapper "credentials" altough I excluded it with defaultUseWrapper(false).

UserDAO

public class UserDAO {
    @JacksonXmlProperty(isAttribute = true)
    private int id;

    private Credentials credentials;
    
    @JacksonXmlProperty(localName = "todos")
    private TasksDAO tasks;

    // getter, setter
}

Credentials

public class Credentials {
    @JacksonXmlProperty(localName = "name")
    @JsonProperty("name")
    private String username;
    private String password;
   
    // getter, setter
}

XmlWrapper config

XmlMapper
                .builder()
                .defaultUseWrapper(false)
                .addModule(new JavaTimeModule())
                .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
                .build()

XML output

<users>
    <user id="1">
        <credentials>
            <password>123</password>
            <name>Steve</name>
        </credentials>
        <todos/>
    </user>
</users>

My goal is to have it flat with user and password. How should I do to remove the wrapper credentials?

Desired Output

<users>
    <user id="1">
        <password>123</password>
        <name>Steve</name>
        <todos/>
    </user>
</users>

Solution

  • Dirty Solution

    UserDAOSerializer.java

    package org.example;
    
    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.databind.SerializerProvider;
    import com.fasterxml.jackson.databind.ser.std.StdSerializer;
    import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
    import java.io.IOException;
    
    public class UserDAOSerializer extends StdSerializer<UserDAO> {
        public UserDAOSerializer() {
            this(null);
        }
    
        public UserDAOSerializer(Class<UserDAO> t) {
            super(t);
        }
    
        @Override
        public void serialize(UserDAO value, JsonGenerator gen, SerializerProvider provider) throws IOException {
            Object jsonGenerator;
            if (gen instanceof ToXmlGenerator) {
                final ToXmlGenerator xmlGenerator = (ToXmlGenerator) gen;
                gen.writeStartObject();
                xmlGenerator.setNextIsAttribute(true);
                gen.writeStringField("id",String.valueOf(value.getId()));
    
                xmlGenerator.setNextIsAttribute(false);
                gen.writeStringField("password",value.getCredentials().getPassword());
                gen.writeStringField("name",value.getCredentials().getUsername());
                gen.writeEndObject();
            } else {
                //TODO JSON MAPPING
            }
        }
    
    }
    

    UserDAO.java

    package org.example;
    
    import com.fasterxml.jackson.databind.annotation.JsonSerialize;
    import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
    
    @JsonSerialize(using = UserDAOSerializer.class)
    public class UserDAO {
        @JacksonXmlProperty(isAttribute = true)
        private int id;
        private Credentials credentials;
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
    
        public Credentials getCredentials() {
            return credentials;
        }
    
        public void setCredentials(Credentials credentials) {
            this.credentials = credentials;
        }
    
    }
    

    Main2.java

    package org.example;
    
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.dataformat.xml.XmlMapper;
    
    public class Main2 {
        public static void main(String[] args) throws JsonProcessingException {
            Credentials c1=new Credentials();
            c1.setUsername("Steve");
            c1.setPassword("123");
            UserDAO u1=new UserDAO();
            u1.setId(1);
            u1.setCredentials(c1);
            XmlMapper xmlMapper = new XmlMapper();
            String s2=xmlMapper.writeValueAsString(u1);
            System.out.println(s2);
        }
    }
    

    Credentials.java

    package org.example;

    import com.fasterxml.jackson.annotation.JsonProperty;

    public class Credentials {
       // @JacksonXmlProperty(localName = "name")
        @JsonProperty("name")
        private String username;
        private String password;
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }
    

    Run Result

    <UserDAO id="1">
        <password>123</password>
        <name>Steve</name>
    </UserDAO>
    

    REF

    Jackson: Registering a custom XML serializer for Map data structure

    @Bender answer

    Conclusion

    I know this is not exactly what you asked for, this is just a POC.

    I think you can handle others.

    I hope this answer can solve your problem.