Code Generators
XML to Java Converter
Paste an XML sample, get typed Java models — names, nesting and nullability inferred for you.
In short
Convert XML to Java online: paste a sample and generate typed Java models with serialization helpers — powered by quicktype, in your browser.
By NaveenKumar T · Updated
- Typed models from one sample
- Nested objects become types
- Nullability inferred
Runs entirely in your browser — nothing you paste or open here is uploaded, logged, or stored.How we handle data →
Example
Example: XML order payload to Java
The same order as XML, with data split between attributes (id, status, paid, sku, qty, price) and element text (name, email, total) — the split that decides which Java fields are typed as numbers and which stay strings. The right-hand side is the exact output of this tool.
<order id="ord_9F2KX" status="processing" paid="true">
<customer>
<name>Ada Lovelace</name>
<email>ada@example.com</email>
</customer>
<items>
<item sku="KB-75" qty="1" price="149.99"/>
<item sku="MS-12" qty="2" price="39.5"/>
</items>
<total>228.99</total>
</order>// Converter.java
// To use this code, add the following Maven dependency to your project:
//
//
// com.fasterxml.jackson.core : jackson-databind : 2.9.0
// com.fasterxml.jackson.datatype : jackson-datatype-jsr310 : 2.9.0
//
// Import this package:
//
// import io.quicktype.Converter;
//
// Then you can deserialize a JSON string with
//
// Root data = Converter.fromJsonString(jsonString);
package io.quicktype;
import java.io.IOException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.*;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
public class Converter {
// Date-time helpers
private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()
.appendOptional(DateTimeFormatter.ISO_DATE_TIME)
.appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
.appendOptional(DateTimeFormatter.ISO_INSTANT)
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SX"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssX"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
.toFormatter()
.withZone(ZoneOffset.UTC);
public static OffsetDateTime parseDateTimeString(String str) {
return ZonedDateTime.from(Converter.DATE_TIME_FORMATTER.parse(str)).toOffsetDateTime();
}
private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder()
.appendOptional(DateTimeFormatter.ISO_TIME)
.appendOptional(DateTimeFormatter.ISO_OFFSET_TIME)
.parseDefaulting(ChronoField.YEAR, 2020)
.parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
.toFormatter()
.withZone(ZoneOffset.UTC);
public static OffsetTime parseTimeString(String str) {
return ZonedDateTime.from(Converter.TIME_FORMATTER.parse(str)).toOffsetDateTime().toOffsetTime();
}
// Serialize/deserialize helpers
public static Root fromJsonString(String json) throws IOException {
return getObjectReader().readValue(json);
}
public static String toJsonString(Root obj) throws JsonProcessingException {
return getObjectWriter().writeValueAsString(obj);
}
private static ObjectReader reader;
private static ObjectWriter writer;
private static void instantiateMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.findAndRegisterModules();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
SimpleModule module = new SimpleModule();
module.addDeserializer(OffsetDateTime.class, new JsonDeserializer<OffsetDateTime>() {
@Override
public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String value = jsonParser.getText();
return Converter.parseDateTimeString(value);
}
});
mapper.registerModule(module);
reader = mapper.readerFor(Root.class);
writer = mapper.writerFor(Root.class);
}
private static ObjectReader getObjectReader() {
if (reader == null) instantiateMapper();
return reader;
}
private static ObjectWriter getObjectWriter() {
if (writer == null) instantiateMapper();
return writer;
}
}
// Root.java
package io.quicktype;
import com.fasterxml.jackson.annotation.*;
public class Root {
private Order order;
@JsonProperty("order")
public Order getOrder() { return order; }
@JsonProperty("order")
public void setOrder(Order value) { this.order = value; }
}
// Order.java
package io.quicktype;
import com.fasterxml.jackson.annotation.*;
public class Order {
private Customer customer;
private Items items;
private double total;
private String id;
private String status;
private String paid;
@JsonProperty("customer")
public Customer getCustomer() { return customer; }
@JsonProperty("customer")
public void setCustomer(Customer value) { this.customer = value; }
@JsonProperty("items")
public Items getItems() { return items; }
@JsonProperty("items")
public void setItems(Items value) { this.items = value; }
@JsonProperty("total")
public double getTotal() { return total; }
@JsonProperty("total")
public void setTotal(double value) { this.total = value; }
@JsonProperty("id")
public String getID() { return id; }
@JsonProperty("id")
public void setID(String value) { this.id = value; }
@JsonProperty("status")
public String getStatus() { return status; }
@JsonProperty("status")
public void setStatus(String value) { this.status = value; }
@JsonProperty("paid")
public String getPaid() { return paid; }
@JsonProperty("paid")
public void setPaid(String value) { this.paid = value; }
}
// Customer.java
package io.quicktype;
import com.fasterxml.jackson.annotation.*;
public class Customer {
private String name;
private String email;
@JsonProperty("name")
public String getName() { return name; }
@JsonProperty("name")
public void setName(String value) { this.name = value; }
@JsonProperty("email")
public String getEmail() { return email; }
@JsonProperty("email")
public void setEmail(String value) { this.email = value; }
}
// Items.java
package io.quicktype;
import com.fasterxml.jackson.annotation.*;
public class Items {
private Item[] item;
@JsonProperty("item")
public Item[] getItem() { return item; }
@JsonProperty("item")
public void setItem(Item[] value) { this.item = value; }
}
// Item.java
package io.quicktype;
import com.fasterxml.jackson.annotation.*;
public class Item {
private String sku;
private String qty;
private String price;
@JsonProperty("sku")
public String getSku() { return sku; }
@JsonProperty("sku")
public void setSku(String value) { this.sku = value; }
@JsonProperty("qty")
public String getQty() { return qty; }
@JsonProperty("qty")
public void setQty(String value) { this.qty = value; }
@JsonProperty("price")
public String getPrice() { return price; }
@JsonProperty("price")
public void setPrice(String value) { this.price = value; }
}
Compare "total" (element text, typed double) with "price" and "qty" (attributes, kept as String). The root <order> element became a nested Order type under Root.
Learn more
From XML sample to Java types
Hand-writing model classes from an XML payload means deciding, field by field, which parser reads which node — this page automates that decision. quicktype first parses your document into a data model, attributes included, then runs the same type inference it uses for JSON against the result.
Decimals become double, so total is 228.99000000000001 the first time you add two of them together. For prices, swap the generated double for BigDecimal and enable USE_BIG_DECIMAL_FOR_FLOATS on the ObjectMapper the Converter builds; the @JsonProperty annotations stay exactly as they are. Integers are safe as they stand — quicktype types them long, which holds a 64-bit ID exactly.
How XML elements and attributes become Java types
The XML is parsed into a data model before inference (attributes included, text nodes named "text"), so the root element becomes a nested type: <order> is a field of type Order on the top-level Root rather than the top level itself. Child elements become fields, and repeated elements — the two <item> siblings — are collected into Item[] under an Items wrapper type that mirrors the <items> container.
Attributes and element text are typed differently, and this matters: element text is type-inferred, so <total>228.99</total> becomes double, while attribute values are kept as they were written — qty="1" and price="149.99" stay String in Java. Prefer element text for numeric data you want typed, or cast attribute values after decoding. One more trap: a single <item> would not be recognized as a list, so make sure repeated elements appear at least twice in the sample.
Reading the XML in Java with the generated types
The classes on this page are Jackson POJOs: the annotations they carry are @JsonProperty, not @JacksonXmlProperty, and nothing in them mentions XML. That is not a dead end — the XmlMapper from jackson-dataformat-xml reads the same annotations, so the generated types double as XML bindings for one extra dependency. One adjustment is needed: XmlMapper binds the document's root element itself, so read into Order rather than Root, which exists only because the generator nests <order> one level down. Field names and nesting below that are identical to JSON to Java.
// pom.xml: com.fasterxml.jackson.dataformat:jackson-dataformat-xml
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// <order> is the document root, so bind Order (not Root).
Order order = xmlMapper.readValue(xmlString, Order.class);
System.out.println(order.getItems().getItem()[0].getSku()); // KB-75Help
Frequently asked questions
Everything you need to know about the XML to Java.
01How do I generate Java classes from XML?
Paste an XML document and press Convert. It is first parsed into a data model — attributes included — then typed: the root element becomes a nested type, repeated elements become Item[], and the result downloads as Root.java.
02Do the generated Java classes read XML directly?
Not with the default ObjectMapper, but with one extra dependency they do: jackson-dataformat-xml's XmlMapper honours the same @JsonProperty annotations. Bind the document's root element — Order, not Root, since Root exists only because the generator nests <order> one level down — and set FAIL_ON_UNKNOWN_PROPERTIES to false.
03Why is there an Items class wrapping an array of Item?
Because the XML has an <items> container around the repeated <item> elements, and the generator mirrors every element as a type. JSON arrays have no wrapper, so the JSON to Java page produces Item[] directly. Flatten it in your own code, or remove the container from the sample if your XML never has one.
04Do XML namespaces affect the generated Java class names?
Namespaces are dropped: XmlMapper binds elements by their local name only, so a document using a namespace like <order xmlns="urn:example"> maps onto Order exactly as this page's undecorated example does, with no @JacksonXmlRootElement needed for the default case. A document mixing multiple namespaces on sibling elements needs @JacksonXmlProperty(namespace=...) added by hand, which one sample cannot infer.
Keep working
Related tools
JSON to Java
Code Generators
XML to TypeScript
Code Generators
XML Formatter
Re-indent any XML document into clean, readable markup — comments and CDATA preserved, validation built in.
XML to C#
Code Generators
WSDL Formatter
Make machine-generated WSDL readable — messages, portTypes, bindings and services cleanly indented and explorable.
XML to Go
Code Generators