杰瑞科技汇

Java XML如何高效转JSON?

Of course! Converting XML to JSON in Java is a common task, but it has nuances. The main challenge is that XML is inherently hierarchical and has attributes, while JSON is a key-value data structure. How you handle attributes, namespaces, and XML text content (mixed content) determines the quality of the resulting JSON.

Java XML如何高效转JSON?-图1
(图片来源网络,侵删)

Here’s a comprehensive guide covering the best libraries, a comparison, and detailed code examples.

The Core Challenge: XML vs. JSON Structure

  • XML Attributes: An element like <person id="123">John</person> has both attributes (id) and text content (John). How do you represent this in JSON?
    • Option A (Recommended): Put attributes in a special @attributes object: {"person": {"@attributes": {"id": "123"}, "#text": "John"}}
    • Option B: Put attributes at the same level as children: {"person": {"id": "123", "#text": "John"}}
    • Option C: Ignore attributes or convert them to keys.
  • XML Namespaces: ns:person adds complexity. Libraries can either ignore them, include them in the key (ns:person), or create a nested structure.
  • Mixed Content: XML like <p>Hello <b>World</b>!</p> is hard to map cleanly to a simple JSON array.

Recommended Libraries

There are two excellent, widely-used libraries for this task:

  1. Jackson with jackson-dataformat-xml: The most popular choice if you're already using Jackson for JSON processing. It's robust, performant, and part of a mature ecosystem.
  2. org.json: A very lightweight and simple library. It's easy to use but less flexible than Jackson for complex scenarios.

Method 1: Using Jackson (Recommended)

This is the most robust and flexible solution. The key is to use XmlMapper, which is the Jackson equivalent of ObjectMapper for XML.

Add Dependency

Add the Jackson XML dataformat dependency to your pom.xml (Maven):

Java XML如何高效转JSON?-图2
(图片来源网络,侵删)
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.15.2</version> <!-- Use the latest version -->
</dependency>

Or for Gradle (build.gradle):

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

Basic Conversion (Simple XML)

Let's start with a straightforward example.

XML (data.xml):

<root>
    <name>John Doe</name>
    <age>30</age>
    <city>New York</city>
</root>

Java Code:

Java XML如何高效转JSON?-图3
(图片来源网络,侵删)
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.File;
import java.io.IOException;
public class JacksonXmlToJsonConverter {
    public static void main(String[] args) {
        try {
            // 1. Create an XmlMapper instance
            XmlMapper xmlMapper = new XmlMapper();
            // 2. Read the XML file into a JsonNode tree
            // You can also use xmlMapper.readValue(new URL("..."), JsonNode.class);
            JsonNode node = xmlMapper.readTree(new File("data.xml"));
            // 3. Create a standard ObjectMapper to write the JSON
            ObjectMapper jsonMapper = new ObjectMapper();
            // 4. Write the JsonNode to a JSON string
            // The 'prettyPrinter()' makes the output human-readable
            String jsonString = jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);
            System.out.println(jsonString);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Output JSON:

{
  "root" : {
    "name" : "John Doe",
    "age" : 30,
    "city" : "New York"
  }
}

Handling Attributes and Complex XML

This is where Jackson shines. By default, it handles attributes using the @attributes convention.

XML (complex_data.xml):

<users>
    <user id="123" status="active">
        <name>Jane Doe</name>
        <email>jane.doe@example.com</email>
    </user>
    <user id="456" status="inactive">
        <name>Bob Smith</name>
        <email>bob.smith@example.com</email>
    </user>
</users>

Java Code:

// (Same setup as before, just reading a different file)
XmlMapper xmlMapper = new XmlMapper();
JsonNode node = xmlMapper.readTree(new File("complex_data.xml"));
ObjectMapper jsonMapper = new ObjectMapper();
String jsonString = jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);
System.out.println(jsonString);

Output JSON:

{
  "users" : {
    "user" : [ {
      "@attributes" : {
        "id" : "123",
        "status" : "active"
      },
      "name" : "Jane Doe",
      "email" : "jane.doe@example.com"
    }, {
      "@attributes" : {
        "id" : "456",
        "status" : "inactive"
      },
      "name" : "Bob Smith",
      "email" : "bob.smith@example.com"
    } ]
  }
}

Notice how:

  • Attributes are neatly placed in an @attributes object.
  • Repeated <user> elements are automatically converted into a JSON array.

Method 2: Using org.json (Lightweight Alternative)

This library is simpler but requires more manual handling of complex structures like attributes.

Add Dependency

Add the org.json dependency to your pom.xml (Maven):

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20251013</version> <!-- Use the latest version -->
</dependency>

Or for Gradle (build.gradle):

implementation 'org.json:json:20251013' // Use the latest version

Basic Conversion

The org.json library doesn't have a direct "XML to JSON" parser. The common approach is to first convert XML to a DOM (Document), then manually walk the DOM tree to build a JSONObject.

Java Code:

import org.json.JSONArray;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
public class OrgJsonXmlConverter {
    public static void main(String[] args) {
        try {
            // 1. Parse the XML file into a DOM Document
            File xmlFile = new File("data.xml");
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(xmlFile);
            // 2. Get the root element
            Element root = document.getDocumentElement();
            // 3. Convert the DOM Element to a JSONObject
            JSONObject jsonObject = xmlToJSONObject(root);
            // 4. Print the JSON string with indentation
            System.out.println(jsonObject.toString(2));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static JSONObject xmlToJSONObject(Element element) {
        JSONObject jsonObject = new JSONObject();
        // 1. Handle attributes
        if (element.hasAttributes()) {
            JSONObject attributes = new JSONObject();
            for (int i = 0; i < element.getAttributes().getLength(); i++) {
                Node attr = element.getAttributes().item(i);
                attributes.put(attr.getNodeName(), attr.getNodeValue());
            }
            jsonObject.put("@attributes", attributes);
        }
        // 2. Handle child nodes
        NodeList nodeList = element.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element childElement = (Element) node;
                String childName = childElement.getNodeName();
                // If the child node already exists, create an array
                if (jsonObject.has(childName)) {
                    Object existing = jsonObject.get(childName);
                    JSONArray array;
                    if (existing instanceof JSONArray) {
                        array = (JSONArray) existing;
                    } else {
                        array = new JSONArray();
                        array.put(existing);
                        jsonObject.put(childName, array);
                    }
                    array.put(xmlToJSONObject(childElement));
                } else {
                    jsonObject.put(childName, xmlToJSONObject(childElement));
                }
            } else if (node.getNodeType() == Node.TEXT_NODE) {
                String textContent = node.getTextContent().trim();
                if (!textContent.isEmpty()) {
                    // This handles simple text content like <name>John</name>
                    // For mixed content, this logic needs to be more complex
                    jsonObject.put("#text", textContent);
                }
            }
        }
        return jsonObject;
    }
}

This org.json approach is more verbose because you have to implement the conversion logic yourself, but it gives you full control. The output will be very similar to Jackson's default format.


Comparison and Recommendation

Feature Jackson (XmlMapper) org.json
Ease of Use Excellent. A single readTree call handles most cases. Fair. Requires manual DOM traversal and logic.
Performance Excellent. Highly optimized. Good. Slightly slower due to manual processing.
Flexibility Excellent. Configurable via annotations and modules. High. You control the logic, but it's more work.
Attribute Handling Built-in & robust. Uses @attributes by default. Manual. You must write the logic to extract them.
Dependency Larger, but often already in projects using Spring, etc. Very small and lightweight.
Best For Most use cases, especially in production applications or when using the Jackson ecosystem. Simple scripts or when you want to avoid a larger dependency and need fine-grained control.

Final Recommendation

For any serious project, use Jackson. It's the industry standard, more reliable, less error-prone, and significantly easier to use. The one-line xmlMapper.readTree() call is powerful and handles the complexities of XML (attributes, arrays, namespaces) gracefully.

Use the org.json library only if you have a very strict dependency constraint and need to perform a simple, one-off conversion where you don't want to add a larger library.

分享:
扫描分享到社交APP
上一篇
下一篇