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

org.apache.juneau.serializer.Serializer 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.serializer;

import java.io.*;

import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.http.*;

/**
 * Parent class for all Juneau serializers.
 *
 * 
Description:
* * Base serializer class that serves as the parent class for all serializers. * *

* The purpose of this class is: *

    *
  • Maintain a read-only configuration state of a serializer (i.e. {@link SerializerContext}). *
  • Create session objects used for serializing POJOs (i.e. {@link SerializerSession}). *
  • Provide convenience methods for serializing POJOs without having to construct session objects. *
* *

* Subclasses should extend directly from {@link OutputStreamSerializer} or {@link WriterSerializer} depending on * whether it's a stream or character based serializer. */ public abstract class Serializer extends CoreObject { //------------------------------------------------------------------------------------------------------------------- // Configurable properties //------------------------------------------------------------------------------------------------------------------- private static final String PREFIX = "Serializer."; /** * Configuration property: Max serialization depth. * *

    *
  • Name: "Serializer.maxDepth" *
  • Data type: Integer *
  • Default: 100 *
  • Session-overridable: true *
* *

* Abort serialization if specified depth is reached in the POJO tree. * If this depth is exceeded, an exception is thrown. * This prevents stack overflows from occurring when trying to serialize models with recursive references. */ public static final String SERIALIZER_maxDepth = PREFIX + "maxDepth"; /** * Configuration property: Initial depth. * *

    *
  • Name: "Serializer.initialDepth" *
  • Data type: Integer *
  • Default: 0 *
  • Session-overridable: true *
* *

* The initial indentation level at the root. * Useful when constructing document fragments that need to be indented at a certain level. */ public static final String SERIALIZER_initialDepth = PREFIX + "initialDepth"; /** * Configuration property: Automatically detect POJO recursions. * *

    *
  • Name: "Serializer.detectRecursions" *
  • Data type: Boolean *
  • Default: false *
  • Session-overridable: true *
* *

* Specifies that recursions should be checked for during serialization. * *

* Recursions can occur when serializing models that aren't true trees, but rather contain loops. * *

* The behavior when recursions are detected depends on the value for {@link #SERIALIZER_ignoreRecursions}. * *

* For example, if a model contains the links A->B->C->A, then the JSON generated will look like * the following when SERIALIZER_ignoreRecursions is true... * {A:{B:{C:null}}} * *

Notes:
*
    *
  • Checking for recursion can cause a small performance penalty. *
*/ public static final String SERIALIZER_detectRecursions = PREFIX + "detectRecursions"; /** * Configuration property: Ignore recursion errors. * *
    *
  • Name: "Serializer.ignoreRecursions" *
  • Data type: Boolean *
  • Default: false *
  • Session-overridable: true *
* *

* Used in conjunction with {@link #SERIALIZER_detectRecursions}. * Setting is ignored if SERIALIZER_detectRecursions is false. * *

* If true, when we encounter the same object when serializing a tree, we set the value to null. * Otherwise, an exception is thrown. */ public static final String SERIALIZER_ignoreRecursions = PREFIX + "ignoreRecursions"; /** * Configuration property: Use whitespace. * *

    *
  • Name: "Serializer.useWhitespace" *
  • Data type: Boolean *
  • Default: false *
  • Session-overridable: true *
* *

* If true, whitespace is added to the output to improve readability. * *

* This setting does not apply to the MessagePack serializer. */ public static final String SERIALIZER_useWhitespace = PREFIX + "useWhitespace"; /** * Configuration property: Maximum indentation. * *

    *
  • Name: "Serializer.maxIndent" *
  • Data type: Integer *
  • Default: 100 *
  • Session-overridable: true *
* *

* Specifies the maximum indentation level in the serialized document. * *

* This setting does not apply to the MessagePack or RDF serializers. */ public static final String SERIALIZER_maxIndent = PREFIX + "maxIndent"; /** * Configuration property: Add "_type" properties when needed. * *

    *
  • Name: "Serializer.addBeanTypeProperties" *
  • Data type: Boolean *
  • Default: true *
  • Session-overridable: true *
* *

* If true, then "_type" properties will be added to beans if their type cannot be inferred * through reflection. * This is used to recreate the correct objects during parsing if the object types cannot be inferred. * For example, when serializing a {@code Map} field, where the bean class cannot be determined from * the value type. */ public static final String SERIALIZER_addBeanTypeProperties = PREFIX + "addBeanTypeProperties"; /** * Configuration property: Quote character. * *

    *
  • Name: "Serializer.quoteChar" *
  • Data type: Character *
  • Default: '"' *
  • Session-overridable: true *
* *

* This is the character used for quoting attributes and values. * *

* This setting does not apply to the MessagePack or RDF serializers. */ public static final String SERIALIZER_quoteChar = PREFIX + "quoteChar"; /** * Configuration property: Trim null bean property values. * *

    *
  • Name: "Serializer.trimNullProperties" *
  • Data type: Boolean *
  • Default: true *
  • Session-overridable: true *
* *

* If true, null bean values will not be serialized to the output. * *

* Note that enabling this setting has the following effects on parsing: *

    *
  • * Map entries with null values will be lost. *
*/ public static final String SERIALIZER_trimNullProperties = PREFIX + "trimNullProperties"; /** * Configuration property: Trim empty lists and arrays. * *
    *
  • Name: "Serializer.trimEmptyLists" *
  • Data type: Boolean *
  • Default: false *
  • Session-overridable: true *
* *

* If true, empty list values will not be serialized to the output. * *

* Note that enabling this setting has the following effects on parsing: *

    *
  • * Map entries with empty list values will be lost. *
  • * Bean properties with empty list values will not be set. *
*/ public static final String SERIALIZER_trimEmptyCollections = PREFIX + "trimEmptyLists"; /** * Configuration property: Trim empty maps. * *
    *
  • Name: "Serializer.trimEmptyMaps" *
  • Data type: Boolean *
  • Default: false *
  • Session-overridable: true *
* *

* If true, empty map values will not be serialized to the output. * *

* Note that enabling this setting has the following effects on parsing: *

    *
  • * Bean properties with empty map values will not be set. *
*/ public static final String SERIALIZER_trimEmptyMaps = PREFIX + "trimEmptyMaps"; /** * Configuration property: Trim strings. * *
    *
  • Name: "Serializer.trimStrings" *
  • Data type: Boolean *
  • Default: false *
  • Session-overridable: true *
* *

* If true, string values will be trimmed of whitespace using {@link String#trim()} before being serialized. */ public static final String SERIALIZER_trimStrings = PREFIX + "trimStrings"; /** * Configuration property: URI context bean. * *

    *
  • Name: "Serializer.uriContext" *
  • Data type: {@link UriContext} *
  • Default: {@link UriContext#DEFAULT} *
  • Session-overridable: true *
* *

* Bean used for resolution of URIs to absolute or root-relative form. * *

Example:
*

* "{authority:'http://localhost:10000',contextRoot:'/myContext',servletPath:'/myServlet',pathInfo:'/foo'}" *

*/ public static final String SERIALIZER_uriContext = PREFIX + "uriContext"; /** * Configuration property: URI resolution. * *
    *
  • Name: "Serializer.uriResolution" *
  • Data type: {@link UriResolution} *
  • Default: {@link UriResolution#NONE} *
  • Session-overridable: true *
* *

* Defines the resolution level for URIs when serializing any of the following: *

    *
  • {@link java.net.URI} *
  • {@link java.net.URL} *
  • Properties annotated with {@link org.apache.juneau.annotation.URI @URI} *
* *

* Possible values are: *

    *
  • {@link UriResolution#ABSOLUTE} * - Resolve to an absolute URL (e.g. "http://host:port/context-root/servlet-path/path-info"). *
  • {@link UriResolution#ROOT_RELATIVE} * - Resolve to a root-relative URL (e.g. "/context-root/servlet-path/path-info"). *
  • {@link UriResolution#NONE} * - Don't do any URL resolution. *
*/ public static final String SERIALIZER_uriResolution = PREFIX + "uriResolution"; /** * Configuration property: URI relativity. * *
    *
  • Name: "Serializer.uriRelativity" *
  • Data type: {@link UriRelativity} *
  • Default: {@link UriRelativity#RESOURCE} *
  • Session-overridable: true *
* *

* Defines what relative URIs are relative to when serializing any of the following: *

    *
  • {@link java.net.URI} *
  • {@link java.net.URL} *
  • Properties annotated with {@link org.apache.juneau.annotation.URI @URI} *
* *

* Possible values are: *

    *
  • {@link UriRelativity#RESOURCE} * - Relative URIs should be considered relative to the servlet URI. *
  • {@link UriRelativity#PATH_INFO} * - Relative URIs should be considered relative to the request URI. *
*/ public static final String SERIALIZER_uriRelativity = PREFIX + "uriRelativity"; /** * Configuration property: Sort arrays and collections alphabetically. * *
    *
  • Name: "Serializer.sortCollections" *
  • Data type: Boolean *
  • Default: false *
  • Session-overridable: true *
* *

* Note that this introduces a performance penalty. */ public static final String SERIALIZER_sortCollections = PREFIX + "sortCollections"; /** * Configuration property: Sort maps alphabetically. * *

    *
  • Name: "Serializer.sortMaps" *
  • Data type: Boolean *
  • Default: false *
  • Session-overridable: true *
* *

* Note that this introduces a performance penalty. */ public static final String SERIALIZER_sortMaps = PREFIX + "sortMaps"; /** * Configuration property: Abridged output. * *

    *
  • Name: "Serializer.abridged" *
  • Data type: Boolean *
  • Default: false *
  • Session-overridable: true *
* *

* When enabled, it is assumed that the parser knows the exact Java POJO type being parsed, and therefore top-level * type information that might normally be included to determine the data type will not be serialized. * *

* For example, when serializing a POJO with a {@link Bean#typeName()} value, a "_type" will be added when * this setting is disabled, but not added when it is enabled. */ public static final String SERIALIZER_abridged = PREFIX + "abridged"; /** * Configuration property: Serializer listener. * *

    *
  • Name: "Serializer.listener" *
  • Data type: Class<? extends SerializerListener> *
  • Default: null *
  • Session-overridable: true *
* *

* Class used to listen for errors and warnings that occur during serialization. */ public static final String SERIALIZER_listener = PREFIX + "listener"; //------------------------------------------------------------------------------------------------------------------- // Instance //------------------------------------------------------------------------------------------------------------------- private final MediaType[] accept; private final MediaType produces; // Hidden constructors to force subclass from OuputStreamSerializer or WriterSerializer. Serializer(PropertyStore propertyStore, String produces, String...accept) { super(propertyStore); this.produces = MediaType.forString(produces); if (accept.length == 0) { this.accept = new MediaType[]{this.produces}; } else { this.accept = new MediaType[accept.length]; for (int i = 0; i < accept.length; i++) { this.accept[i] = MediaType.forString(accept[i]); } } } @Override /* CoreObject */ public SerializerBuilder builder() { return new SerializerBuilder(propertyStore); } //-------------------------------------------------------------------------------- // Abstract methods //-------------------------------------------------------------------------------- /** * Returns true if this serializer subclasses from {@link WriterSerializer}. * * @return true if this serializer subclasses from {@link WriterSerializer}. */ public abstract boolean isWriterSerializer(); /** * Create the session object used for actual serialization of objects. * * @param args * Runtime arguments. * These specify session-level information such as locale and URI context. * It also include session-level properties that override the properties defined on the bean and serializer * contexts. * @return * The new session object. *
Note that you must call {@link SerializerSession#close()} on this object to perform any necessary * cleanup. */ public abstract SerializerSession createSession(SerializerSessionArgs args); //-------------------------------------------------------------------------------- // Convenience methods //-------------------------------------------------------------------------------- /** * Shortcut for calling createSession(null). * * @return * The new session object. *
Note that you must call {@link SerializerSession#close()} on this object to perform any necessary * cleanup. */ public final SerializerSession createSession() { return createSession(createDefaultSessionArgs()); } /** * Creates the session arguments object that gets passed to the {@link #createSession(SerializerSessionArgs)} method. * * @return * A new default session arguments object. *

The arguments can be modified before passing to the {@link #createSession(SerializerSessionArgs)}. */ public final SerializerSessionArgs createDefaultSessionArgs() { return new SerializerSessionArgs(ObjectMap.EMPTY_MAP, null, null, null, getResponseContentType(), null); } /** * Serializes a POJO to the specified output stream or writer. * *

* Equivalent to calling serializer.createSession().serialize(o, output); * * @param o The object to serialize. * @param output * The output object. *
Character-based serializers can handle the following output class types: *

    *
  • {@link Writer} *
  • {@link OutputStream} - Output will be written as UTF-8 encoded stream. *
  • {@link File} - Output will be written as system-default encoded stream. *
  • {@link StringBuilder} - Output will be written to the specified string builder. *
*
Stream-based serializers can handle the following output class types: *
    *
  • {@link OutputStream} *
  • {@link File} *
* @throws SerializeException If a problem occurred trying to convert the output. */ public final void serialize(Object o, Object output) throws SerializeException { SerializerSession s = createSession(); try { s.serialize(o, output); } finally { s.close(); } } /** * Shortcut method for serializing objects directly to either a String or byte[] * depending on the serializer type. * * @param o The object to serialize. * @return * The serialized object. *
Character-based serializers will return a String *
Stream-based serializers will return a byte[] * @throws SerializeException If a problem occurred trying to convert the output. */ public Object serialize(Object o) throws SerializeException { SerializerSession s = createSession(); try { return s.serialize(o); } finally { s.close(); } } //-------------------------------------------------------------------------------- // Other methods //-------------------------------------------------------------------------------- /** * Returns the media types handled based on the value of the accept parameter passed into the constructor. * * @return The list of media types. Never null. */ public final MediaType[] getMediaTypes() { return accept; } /** * Optional method that returns the response Content-Type for this serializer if it is different from * the matched media type. * *

* This method is specified to override the content type for this serializer. * For example, the {@link org.apache.juneau.json.JsonSerializer.Simple} class returns that it handles media type * "text/json+simple", but returns "text/json" as the actual content type. * This allows clients to request specific 'flavors' of content using specialized Accept header values. * *

* This method is typically meaningless if the serializer is being used stand-alone (i.e. outside of a REST server * or client). * * @return The response content type. If null, then the matched media type is used. */ public final MediaType getResponseContentType() { return produces; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy