杰瑞科技汇

如何将XML高效转为Java Bean对象?

Of course! Converting XML to a Java Bean (also known as deserialization or unmarshalling) is a common task in enterprise applications. There are several excellent libraries to achieve this, with JAXB (Java Architecture for XML Binding) being the standard for Java (pre-Java 11) and Jackson being a very popular and flexible alternative.

Here’s a comprehensive guide covering both, starting with the most straightforward method for modern Java projects.


Summary of Approaches

Library How it Works Pros Cons Best For
JAXB Annotations on POJOs. Built into Java (but removed from standard library after Java 8). Standard for Java EE, easy to set up, good performance. Requires adding dependency for Java 9+, less flexible than Jackson for complex JSON/XML. Standard Java EE applications, projects already using JAXB.
Jackson Annotations on POJOs. A powerful data-processing library. Extremely flexible, handles complex JSON/XML well, large community, actively maintained. Can have a steeper learning curve for advanced features. Modern applications, microservices, complex data structures, projects that might also use JSON.
Simple Manual parsing with DocumentBuilderFactory and XPath. No external dependencies, full control. Verbose, error-prone, lots of boilerplate code. Simple, one-off scripts or when you cannot add any external libraries.

Method 1: Using Jackson (Recommended for Modern Projects)

Jackson is a fantastic choice because it's powerful, widely used, and handles both JSON and XML seamlessly.

Step 1: Add the Jackson Dependency

If you're using a build tool like Maven, add the following dependency to your pom.xml:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.15.2</version> <!-- Use the latest version -->
</dependency>

For Gradle (build.gradle):

implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2' // Use the latest version

Step 2: Create the Java Bean (POJO)

Your Java class must match the structure of your XML. Use Jackson's annotations to map XML elements to Java fields.

XML File (user.xml):

<?xml version="1.0" encoding="UTF-8"?>
<user>
    <id>101</id>
    <name>John Doe</name>
    <email>john.doe@example.com</email>
    <active>true</active>
    <roles>
        <role>ADMIN</role>
        <role>USER</role>
    </roles>
</user>

Java Bean (User.java):

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
// Maps the root element <user> to this class
@JacksonXmlRootElement(localName = "user")
public class User {
    // Maps <id> to the 'id' field
    @JacksonXmlProperty(localName = "id")
    private int id;
    // Maps <name> to the 'name' field
    @JacksonXmlProperty(localName = "name")
    private String name;
    // Maps <email> to the 'email' field
    @JacksonXmlProperty(localName = "email")
    private String email;
    // Maps <active> to the 'active' field
    @JacksonXmlProperty(localName = "active")
    private boolean active;
    // Handles the list of <role> elements
    // @JacksonXmlElementWrapper can be used to specify the wrapper element name (e.g., <roles>)
    @JacksonXmlElementWrapper(localName = "roles")
    @JacksonXmlProperty(localName = "role")
    private java.util.List<String> roles;
    // Getters and Setters are required for Jackson to work
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public boolean isActive() { return active; }
    public void setActive(boolean active) { this.active = active; }
    public java.util.List<String> getRoles() { return roles; }
    public void setRoles(java.util.List<String> roles) { this.roles = roles; }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", active=" + active +
                ", roles=" + roles +
                '}';
    }
}

Step 3: Write the Java Code to Perform the Conversion

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.File;
import java.io.IOException;
public class XmlToJavaBeanConverter {
    public static void main(String[] args) {
        // 1. Create an XmlMapper instance
        XmlMapper xmlMapper = new XmlMapper();
        try {
            // 2. Read the XML file and map it to the User object
            // The 'File' object points to your XML file
            User user = xmlMapper.readValue(new File("user.xml"), User.class);
            // 3. Print the resulting Java object
            System.out.println("Successfully converted XML to Java Bean:");
            System.out.println(user);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Output:

Successfully converted XML to Java Bean:
User{id=101, name='John Doe', email='john.doe@example.com', active=true, roles=[ADMIN, USER]}

Method 2: Using JAXB (The Traditional Java Standard)

JAXB was the built-in standard for Java 8 and earlier. It's still excellent and works perfectly if you add the dependency for newer Java versions.

Step 1: Add the JAXB Dependency

JAXB is no longer part of the standard JDK, so you need to add it.

Maven (pom.xml):

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.1</version>
</dependency>

Step 2: Create the Java Bean with JAXB Annotations

The structure is very similar to Jackson, but the annotations are different.

Java Bean (User.java):

import javax.xml.bind.annotation.*;
import java.util.List;
// Maps the root element <user> to this class
@XmlRootElement(name = "user")
@XmlAccessorType(XmlAccessType.FIELD) // Tells JAXB to use fields directly
public class User {
    // Maps <id> to the 'id' field
    @XmlElement(name = "id")
    private int id;
    // Maps <name> to the 'name' field
    @XmlElement(name = "name")
    private String name;
    // Maps <email> to the 'email' field
    @XmlElement(name = "email")
    private String email;
    // Maps <active> to the 'active' field
    @XmlElement(name = "active")
    private boolean active;
    // Handles the list of <role> elements
    @XmlElementWrapper(name = "roles") // Specifies the wrapper element <roles>
    @XmlElement(name = "role")         // Specifies each element in the list is <role>
    private List<String> roles;
    // Getters and Setters are required
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public boolean isActive() { return active; }
    public void setActive(boolean active) { this.active = active; }
    public List<String> getRoles() { return roles; }
    public void setRoles(List<String> roles) { this.roles = roles; }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", active=" + active +
                ", roles=" + roles +
                '}';
    }
}

Step 3: Write the Java Code to Perform the Conversion

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
public class XmlToJavaBeanConverterJaxb {
    public static void main(String[] args) {
        try {
            // 1. Create a JAXBContext instance for the User class
            JAXBContext jaxbContext = JAXBContext.newInstance(User.class);
            // 2. Create an Unmarshaller
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            // 3. Unmarshal the XML file into a User object
            User user = (User) jaxbUnmarshaller.unmarshal(new File("user.xml"));
            // 4. Print the resulting Java object
            System.out.println("Successfully converted XML to Java Bean using JAXB:");
            System.out.println(user);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}

Handling More Complex XML Structures

Sometimes, your XML has nested objects.

Complex XML (company.xml):

<company>
    <name>TechCorp Inc.</name>
    <ceo>
        <id>1</id>
        <name>Jane Smith</name>
    </ceo>
    <employees>
        <employee>
            <id>101</id>
            <name>John Doe</name>
        </employee>
    </employees>
</company>

Solution:

  1. Create a CEO Java bean and an Employee Java bean, just like the User bean above.
  2. Update your Company bean to have fields of type CEO and List<Employee>.

Java Bean (Company.java):

import javax.xml.bind.annotation.*;
import java.util.List;
@XmlRootElement(name = "company")
@XmlAccessorType(XmlAccessType.FIELD)
public class Company {
    @XmlElement(name = "name")
    private String name;
    // This field will be mapped to the <ceo> element
    @XmlElement(name = "ceo")
    private CEO ceo;
    // This field will be mapped to the <employees> list
    @XmlElementWrapper(name = "employees")
    @XmlElement(name = "employee")
    private List<Employee> employees;
    // Getters, Setters, toString...
}
// CEO.java
@XmlAccessorType(XmlAccessType.FIELD)
public class CEO {
    @XmlElement(name = "id")
    private int id;
    @XmlElement(name = "name")
    private String name;
    // Getters, Setters...
}
// Employee.java
@XmlAccessorType(XmlAccessType.FIELD)
public class Employee {
    @XmlElement(name = "id")
    private int id;
    @XmlElement(name = "name")
    private String name;
    // Getters, Setters...
}

The conversion code remains almost identical. The JAXB/Jackson framework will automatically handle the nested object creation.

Which One Should I Choose?

  • For a new project, especially one that might also handle JSON: Choose Jackson. It's a modern, powerful, and versatile library.
  • For a legacy Java EE project or if you're mandated to use the old standard: Choose JAXB. It's clean, effective, and well-understood in the Java enterprise world.
  • Avoid manual parsing unless you have a very specific, simple reason to do so. The boilerplate code is not worth the effort.
分享:
扫描分享到社交APP
上一篇
下一篇