All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.juneau.xml.XmlSerializer Maven / Gradle / Ivy

There is a newer version: 9.0.1
Show newest version
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
// * with the License.  You may obtain a copy of the License at                                                              *
// *                                                                                                                         *
// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
// *                                                                                                                         *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
// * specific language governing permissions and limitations under the License.                                              *
// ***************************************************************************************************************************
package org.apache.juneau.xml;

import org.apache.juneau.*;
import org.apache.juneau.json.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.xmlschema.*;

/**
 * Serializes POJO models to XML.
 *
 * 
Media types
* * Handles Accept types: text/xml *

* Produces Content-Type types: text/xml * *

Description
* * See the {@link JsonSerializer} class for details on how Java models map to JSON. * *

* For example, the following JSON... *

* { * name:'John Smith', * address: { * streetAddress: '21 2nd Street', * city: 'New York', * state: 'NY', * postalCode: 10021 * }, * phoneNumbers: [ * '212 555-1111', * '212 555-2222' * ], * additionalInfo: null, * remote: false, * height: 62.4, * 'fico score': ' > 640' * } *

* ...maps to the following XML using the default serializer... *

* <object> * <name>John Smith</name> * <address> * <streetAddress>21 2nd Street</streetAddress> * <city>New York</city> * <state>NY</state> * <postalCode>10021</postalCode> * </address> * <phoneNumbers> * <string>212 555-1111</string> * <string>212 555-2222</string> * </phoneNumbers> * <additionalInfo _type='null'></additionalInfo> * <remote>false</remote> * <height>62.4</height> * <fico_x0020_score> &gt; 640</fico_x0020_score> * </object> * *

* An additional "add-json-properties" mode is also provided to prevent loss of JSON data types... *

* <name _type='string'>John Smith</name> * <address _type='object'> * <streetAddress _type='string'>21 2nd Street</streetAddress> * <city _type='string'>New York</city> * <state _type='string'>NY</state> * <postalCode _type='number'>10021</postalCode> * </address> * <phoneNumbers _type='array'> * <string>212 555-1111</string> * <string>212 555-2222</string> * </phoneNumbers> * <additionalInfo _type='null'></additionalInfo> * <remote _type='boolean'>false</remote> * <height _type='number'>62.4</height> * <fico_x0020_score _type='string'> &gt; 640</fico_x0020_score> * </object> *

* *

* This serializer provides several serialization options. * Typically, one of the predefined DEFAULT serializers will be sufficient. * However, custom serializers can be constructed to fine-tune behavior. * *

* If an attribute name contains any non-valid XML element characters, they will be escaped using standard * {@code _x####_} notation. * *

Behavior-specific subclasses
* * The following direct subclasses are provided for convenience: *
    *
  • {@link Sq} - Default serializer, single quotes. *
  • {@link SqReadable} - Default serializer, single quotes, whitespace added. *
*/ public class XmlSerializer extends WriterSerializer { //------------------------------------------------------------------------------------------------------------------- // Configurable properties //------------------------------------------------------------------------------------------------------------------- private static final String PREFIX = "XmlSerializer."; /** * Configuration property: Add "_type" properties when needed. * *
Property:
*
    *
  • Name: "XmlSerializer.addBeanTypes.b" *
  • Data type: Boolean *
  • Default: false *
  • Session property: false *
  • Methods: *
      *
    • {@link XmlSerializerBuilder#addBeanTypes(boolean)} *
    *
* *
Description:
*

* If true, then "_type" properties will be added to beans if their type cannot be inferred * through reflection. * *

* When present, this value overrides the {@link #SERIALIZER_addBeanTypes} setting and is * provided to customize the behavior of specific serializers in a {@link SerializerGroup}. */ public static final String XML_addBeanTypes = PREFIX + "addBeanTypes.b"; /** * Configuration property: Add namespace URLs to the root element. * *

Property:
*
    *
  • Name: "XmlSerializer.addNamespaceUrisToRoot.b" *
  • Data type: Boolean *
  • Default: false *
  • Session property: false *
  • Methods: *
      *
    • {@link XmlSerializerBuilder#addNamespaceUrisToRoot(boolean)} *
    • {@link XmlSerializerBuilder#addNamespaceUrisToRoot()} *
    *
* *
Description:
*

* Use this setting to add {@code xmlns:x} attributes to the root element for the default and all mapped namespaces. * *

* This setting is ignored if {@link #XML_enableNamespaces} is not enabled. * *

See Also:
*
    *
*/ public static final String XML_addNamespaceUrisToRoot = PREFIX + "addNamespaceUrisToRoot.b"; /** * Configuration property: Auto-detect namespace usage. * *
Property:
*
    *
  • Name: "XmlSerializer.autoDetectNamespaces.b" *
  • Data type: Boolean *
  • Default: true *
  • Session property: false *
  • Methods: *
      *
    • {@link XmlSerializerBuilder#autoDetectNamespaces(boolean)} *
    *
* *
Description:
*

* Detect namespace usage before serialization. * *

* Used in conjunction with {@link #XML_addNamespaceUrisToRoot} to reduce the list of namespace URLs appended to the * root element to only those that will be used in the resulting document. * *

* If enabled, then the data structure will first be crawled looking for namespaces that will be encountered before * the root element is serialized. * *

* This setting is ignored if {@link #XML_enableNamespaces} is not enabled. * *

Notes:
*
    *
  • * Auto-detection of namespaces can be costly performance-wise. *
    In high-performance environments, it's recommended that namespace detection be * disabled, and that namespaces be manually defined through the {@link #XML_namespaces} property. *
* *
See Also:
*
    *
*/ public static final String XML_autoDetectNamespaces = PREFIX + "autoDetectNamespaces.b"; /** * Configuration property: Default namespace. * *
Property:
*
    *
  • Name: "XmlSerializer.defaultNamespace.s" *
  • Data type: String ({@link Namespace}) *
  • Default: "juneau: http://www.apache.org/2013/Juneau" *
  • Session property: false *
  • Methods: *
      *
    • {@link XmlSerializerBuilder#defaultNamespace(String)} *
    *
* *
Description:
*

* Specifies the default namespace URI for this document. * *

See Also:
*
    *
*/ public static final String XML_defaultNamespace = PREFIX + "defaultNamespace.s"; /** * Configuration property: Enable support for XML namespaces. * *
Property:
*
    *
  • Name: "XmlSerializer.enableNamespaces.b" *
  • Data type: Boolean *
  • Default: false *
  • Session property: false *
  • Methods: *
      *
    • {@link XmlSerializerBuilder#enableNamespaces(boolean)} *
    *
* *
Description:
*

* If not enabled, XML output will not contain any namespaces regardless of any other settings. * *

See Also:
*
    *
*/ public static final String XML_enableNamespaces = PREFIX + "enableNamespaces.b"; /** * Configuration property: Default namespaces. * *
Property:
*
    *
  • Name: "XmlSerializer.namespaces.ls" *
  • Data type: Set<String> ({@link Namespace}) *
  • Default: empty set *
  • Session property: false *
  • Methods: *
      *
    • {@link XmlSerializerBuilder#defaultNamespace(String)} *
    *
* *
Description:
*

* The default list of namespaces associated with this serializer. * *

See Also:
*
    *
*/ public static final String XML_namespaces = PREFIX + "namespaces.ls"; /** * Configuration property: XMLSchema namespace. * *
Property:
*
    *
  • Name: "XmlSerializer.xsNamespace.s" *
  • Data type: String ({@link Namespace}) *
  • Default: "xs: http://www.w3.org/2001/XMLSchema" *
  • Session property: false *
  • Methods: *
      *
    • {@link XmlSerializerBuilder#xsNamespace(Namespace)} *
    *
* *
Description:
*

* Specifies the namespace for the XMLSchema namespace, used by the schema generated by the * {@link XmlSchemaSerializer} class. * *

See Also:
*
    *
*/ public static final String XML_xsNamespace = PREFIX + "xsNamespace.s"; //------------------------------------------------------------------------------------------------------------------- // Predefined instances //------------------------------------------------------------------------------------------------------------------- /** Default serializer without namespaces. */ public static final XmlSerializer DEFAULT = new XmlSerializer(PropertyStore.DEFAULT); /** Default serializer without namespaces, with single quotes. */ public static final XmlSerializer DEFAULT_SQ = new Sq(PropertyStore.DEFAULT); /** Default serializer without namespaces, with single quotes, whitespace added. */ public static final XmlSerializer DEFAULT_SQ_READABLE = new SqReadable(PropertyStore.DEFAULT); /** Default serializer, all default settings. */ public static final XmlSerializer DEFAULT_NS = new Ns(PropertyStore.DEFAULT); /** Default serializer, single quotes. */ public static final XmlSerializer DEFAULT_NS_SQ = new NsSq(PropertyStore.DEFAULT); /** Default serializer, single quotes, whitespace added. */ public static final XmlSerializer DEFAULT_NS_SQ_READABLE = new NsSqReadable(PropertyStore.DEFAULT); //------------------------------------------------------------------------------------------------------------------- // Predefined subclasses //------------------------------------------------------------------------------------------------------------------- /** Default serializer, single quotes. */ public static class Sq extends XmlSerializer { /** * Constructor. * * @param ps The property store containing all the settings for this object. */ public Sq(PropertyStore ps) { super( ps.builder() .set(WSERIALIZER_quoteChar, '\'') .build() ); } } /** Default serializer, single quotes, whitespace added. */ public static class SqReadable extends XmlSerializer { /** * Constructor. * * @param ps The property store containing all the settings for this object. */ public SqReadable(PropertyStore ps) { super( ps.builder() .set(WSERIALIZER_quoteChar, '\'') .set(SERIALIZER_useWhitespace, true) .build() ); } } /** Default serializer without namespaces. */ public static class Ns extends XmlSerializer { /** * Constructor. * * @param ps The property store containing all the settings for this object. */ public Ns(PropertyStore ps) { super( ps.builder() .set(XML_enableNamespaces, true) .build(), "text/xml", "text/xml+simple" ); } } /** Default serializer without namespaces, single quotes. */ public static class NsSq extends XmlSerializer { /** * Constructor. * * @param ps The property store containing all the settings for this object. */ public NsSq(PropertyStore ps) { super( ps.builder() .set(XML_enableNamespaces, true) .set(WSERIALIZER_quoteChar, '\'') .build() ); } } /** Default serializer without namespaces, single quotes, with whitespace. */ public static class NsSqReadable extends XmlSerializer { /** * Constructor. * * @param ps The property store containing all the settings for this object. */ public NsSqReadable(PropertyStore ps) { super( ps.builder() .set(XML_enableNamespaces, true) .set(WSERIALIZER_quoteChar, '\'') .set(SERIALIZER_useWhitespace, true) .build() ); } } @SuppressWarnings("javadoc") protected static final Namespace DEFAULT_JUNEAU_NAMESPACE = Namespace.create("juneau", "http://www.apache.org/2013/Juneau"), DEFAULT_XS_NAMESPACE = Namespace.create("xs", "http://www.w3.org/2001/XMLSchema"); //------------------------------------------------------------------------------------------------------------------- // Instance //------------------------------------------------------------------------------------------------------------------- private final boolean autoDetectNamespaces, enableNamespaces, addNamespaceUrlsToRoot, addBeanTypes; private final Namespace defaultNamespace; private final Namespace xsNamespace; private final Namespace[] namespaces; private volatile XmlSchemaSerializer schemaSerializer; /** * Constructor. * * @param ps * The property store containing all the settings for this object. */ public XmlSerializer(PropertyStore ps) { this(ps, "text/xml", null); } /** * Constructor. * * @param ps * The property store containing all the settings for this object. * @param produces * The media type that this serializer produces. * @param accept * The accept media types that the serializer can handle. *

* Can contain meta-characters per the media-type specification of {@doc RFC2616.section14.1} *

* If empty, then assumes the only media type supported is produces. *

* For example, if this serializer produces "application/json" but should handle media types of * "application/json" and "text/json", then the arguments should be: *

* super(ps, "application/json", "application/json,text/json"); *

*
...or... *

* super(ps, "application/json", "*​/json"); *

*

* The accept value can also contain q-values. */ public XmlSerializer(PropertyStore ps, String produces, String accept) { super(ps, produces, accept); autoDetectNamespaces = getBooleanProperty(XML_autoDetectNamespaces, true); enableNamespaces = getBooleanProperty(XML_enableNamespaces, false); addNamespaceUrlsToRoot = getBooleanProperty(XML_addNamespaceUrisToRoot, false); defaultNamespace = getInstanceProperty(XML_defaultNamespace, Namespace.class, DEFAULT_JUNEAU_NAMESPACE); addBeanTypes = getBooleanProperty(XML_addBeanTypes, getBooleanProperty(SERIALIZER_addBeanTypes, false)); xsNamespace = getInstanceProperty(XML_xsNamespace, Namespace.class, DEFAULT_XS_NAMESPACE); namespaces = getInstanceArrayProperty(XML_namespaces, Namespace.class, new Namespace[0]); } @Override /* Context */ public XmlSerializerBuilder builder() { return new XmlSerializerBuilder(getPropertyStore()); } /** * Instantiates a new clean-slate {@link XmlSerializerBuilder} object. * *

* This is equivalent to simply calling new XmlSerializerBuilder(). * *

* Note that this method creates a builder initialized to all default settings, whereas {@link #builder()} copies * the settings of the object called on. * * @return A new {@link XmlSerializerBuilder} object. */ public static XmlSerializerBuilder create() { return new XmlSerializerBuilder(); } /** * Returns the schema serializer based on the settings of this serializer. * @return The schema serializer. */ public XmlSerializer getSchemaSerializer() { if (schemaSerializer == null) schemaSerializer = builder().build(XmlSchemaSerializer.class); return schemaSerializer; } @Override /* Serializer */ public WriterSerializerSession createSession(SerializerSessionArgs args) { return new XmlSerializerSession(this, args); } //----------------------------------------------------------------------------------------------------------------- // Properties //----------------------------------------------------------------------------------------------------------------- /** * Configuration property: Auto-detect namespace usage. * * @see #XML_autoDetectNamespaces * @return * true if namespace usage is detected before serialization. */ protected final boolean isAutoDetectNamespaces() { return autoDetectNamespaces; } /** * Configuration property: Enable support for XML namespaces. * * @see #XML_enableNamespaces * @return * false if XML output will not contain any namespaces regardless of any other settings. */ protected final boolean isEnableNamespaces() { return enableNamespaces; } /** * Configuration property: Add namespace URLs to the root element. * * @see #XML_addNamespaceUrisToRoot * @return * true if {@code xmlns:x} attributes are added to the root element for the default and all mapped namespaces. */ protected final boolean isAddNamespaceUrlsToRoot() { return addNamespaceUrlsToRoot; } /** * Configuration property: Add "_type" properties when needed. * * @see #XML_addBeanTypes * @return * true if"_type" properties will be added to beans if their type cannot be inferred * through reflection. */ @Override protected boolean isAddBeanTypes() { return addBeanTypes; } /** * Configuration property: Default namespace. * * @see #XML_defaultNamespace * @return * The default namespace URI for this document. */ protected final Namespace getDefaultNamespace() { return defaultNamespace; } /** * Configuration property: XMLSchema namespace. * * @see #XML_xsNamespace * @return * The namespace for the XMLSchema namespace, used by the schema generated by the * {@link XmlSchemaSerializer} class. */ protected final Namespace getXsNamespace() { return xsNamespace; } /** * Configuration property: Default namespaces. * * @see #XML_namespaces * @return * The default list of namespaces associated with this serializer. */ protected final Namespace[] getNamespaces() { return namespaces; } @Override /* Context */ public ObjectMap asMap() { return super.asMap() .append("XmlSerializer", new ObjectMap() .append("autoDetectNamespaces", autoDetectNamespaces) .append("enableNamespaces", enableNamespaces) .append("addNamespaceUrlsToRoot", addNamespaceUrlsToRoot) .append("defaultNamespace", defaultNamespace) .append("xsNamespace", xsNamespace) .append("namespaces", namespaces) .append("addBeanTypes", addBeanTypes) ); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy