You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JAXB自定义对象/元素名称:新手Schema类生成及Rest XML问题

Hey there! Let's break down how to customize your XML element/object names with that auto-generated JAXB class—since you can't touch the original schema or the generated CustomerType code, we've got a few solid workarounds to get this done.

Option 1: Regenerate Classes with External Bindings (Cleanest if Possible)

If you still have access to run the XJC (JAXB binding compiler) to regenerate your Java classes, you can use an external bindings file to override the default schema-to-Java mappings—no changes needed to your original schema.

First, create a bindings file (e.g., custom-bindings.xml):

<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               version="2.1">
    <!-- Point to your target schema file -->
    <jaxb:bindings schemaLocation="your-original-schema.xsd">
        <!-- Target the CustomerType complex type -->
        <jaxb:bindings node="//xs:complexType[@name='CustomerType']">
            <!-- Rename the generated XML type (and optionally the Java class) -->
            <jaxb:class name="Customer"/>
            <!-- You can also rename individual fields here if needed -->
            <jaxb:bindings node="//xs:element[@name='field1']">
                <jaxb:property name="customerFirstName"/>
            </jaxb:bindings>
        </jaxb:bindings>
    </jaxb:bindings>
</jaxb:bindings>

Then run XJC with this bindings file to regenerate your classes:

xjc -b custom-bindings.xml your-original-schema.xsd

The new Customer class will have @XmlType(name = "Customer", ...) instead of CustomerType, so your XML output will use the name you want.

Option 2: Wrap the Generated Class with an XmlAdapter (No Regeneration Needed)

If you can't regenerate the CustomerType class, an XmlAdapter is a straightforward way to wrap the existing class and define custom element names for serialization.

First, create a wrapper class that defines your desired XML element name:

public class CustomerWrapper {
    @XmlElement(name = "Customer") // This is your custom element name
    private CustomerType customer;

    // Required no-arg constructor for JAXB
    public CustomerWrapper() {}

    public CustomerWrapper(CustomerType customer) {
        this.customer = customer;
    }

    // Getters and setters
    public CustomerType getCustomer() { return customer; }
    public void setCustomer(CustomerType customer) { this.customer = customer; }
}

Next, create the adapter to convert between CustomerType and CustomerWrapper:

public class CustomerTypeAdapter extends XmlAdapter<CustomerWrapper, CustomerType> {
    @Override
    public CustomerType unmarshal(CustomerWrapper wrapper) throws Exception {
        return wrapper.getCustomer();
    }

    @Override
    public CustomerWrapper marshal(CustomerType customer) throws Exception {
        return new CustomerWrapper(customer);
    }
}

Finally, apply this adapter to your REST endpoint. For JAX-RS, add the @XmlJavaTypeAdapter annotation to your resource method:

@GET
@Produces(MediaType.APPLICATION_XML)
@XmlJavaTypeAdapter(CustomerTypeAdapter.class)
public CustomerType getCustomer() {
    CustomerType customer = new CustomerType();
    // Populate field1, field2 etc.
    return customer;
}

When your endpoint returns a CustomerType, JAXB will use the adapter to serialize it as <Customer> instead of <CustomerType>.

Option 3: Customize JAXBContext (Advanced, for Bulk Changes)

If you need to modify multiple mappings or prefer not to use adapters, you can customize the JAXBContext itself. A common approach here is using EclipseLink MOXy (a JAXB implementation) with an external metadata file to override annotations without touching the generated class.

First, create an MOXy mapping file (e.g., oxm-mappings.xml):

<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
              package-name="com.your.package">
    <java-types>
        <java-type name="CustomerType">
            <!-- Rename the XML type -->
            <xml-type name="Customer"/>
            <!-- Rename individual fields if needed -->
            <java-attributes>
                <xml-element java-attribute="field1" name="customerField1"/>
                <xml-element java-attribute="field2" name="customerField2"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

Then, create a ContextResolver in your JAX-RS app to load this custom mapping:

@Provider
public class CustomJAXBContextResolver implements ContextResolver<JAXBContext> {
    private final JAXBContext context;

    public CustomJAXBContextResolver() {
        try {
            Map<String, Object> props = new HashMap<>();
            // Point MOXy to your external mapping file
            props.put(JAXBContextProperties.OXM_METADATA_SOURCE, "oxm-mappings.xml");
            context = JAXBContext.newInstance(new Class[]{CustomerType.class}, props);
        } catch (JAXBException e) {
            throw new RuntimeException("Failed to create custom JAXBContext", e);
        }
    }

    @Override
    public JAXBContext getContext(Class<?> type) {
        return type.equals(CustomerType.class) ? context : null;
    }
}

MOXy will use this external mapping to generate XML, overriding the annotations in the original CustomerType class.


内容的提问来源于stack exchange,提问作者Sethiel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:01:18