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

groovy.json.JsonGenerator Maven / Gradle / Ivy

There is a newer version: 5.0.0-alpha-10
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 groovy.json;

import groovy.lang.Closure;
import groovy.transform.stc.ClosureParams;
import groovy.transform.stc.FromString;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Set;
import java.util.TimeZone;

/**
 * Generates JSON from objects.
 *
 * The {@link Options} builder can be used to configure an instance of a JsonGenerator.
 *
 * @see Options#build()
 * @since 2.5.0
 */
public interface JsonGenerator {

    /**
     * Converts an object to its JSON representation.
     *
     * @param object to convert to JSON
     * @return JSON
     */
    String toJson(Object object);

    /**
     * Indicates whether this JsonGenerator is configured to exclude fields by
     * the given name.
     *
     * @param name of the field
     * @return true if that field is being excluded, else false
     */
    boolean isExcludingFieldsNamed(String name);

    /**
     * Indicates whether this JsonGenerator is configured to exclude values
     * of the given object (may be {@code null}).
     *
     * @param value an instance of an object
     * @return true if values like this are being excluded, else false
     */
    boolean isExcludingValues(Object value);

    /**
     * Handles converting a given type.
     *
     * @since 2.5.0
     */
    interface Converter {

        /**
         * Returns {@code true} if this converter can handle conversions
         * of the given type.
         *
         * @param type the type of the object to convert
         * @return {@code true} if this converter can successfully convert values of
         *      the given type, else {@code false}
         */
        boolean handles(Class type);

        /**
         * Converts a given object.
         *
         * @param value the object to convert
         * @param key the key name for the value, may be {@code null}
         * @return the converted object
         */
        Object convert(Object value, String key);

    }

    /**
     * A builder used to construct a {@link JsonGenerator} instance that allows
     * control over the serialized JSON output.  If you do not need to customize the
     * output it is recommended to use the static {@code JsonOutput.toJson} methods.
     *
     * 

* Example: *


     *     def generator = new groovy.json.JsonGenerator.Options()
     *                         .excludeNulls()
     *                         .dateFormat('yyyy')
     *                         .excludeFieldsByName('bar', 'baz')
     *                         .excludeFieldsByType(java.sql.Date)
     *                         .build()
     *
     *     def input = [foo: null, lastUpdated: Date.parse('yyyy-MM-dd', '2014-10-24'),
     *                   bar: 'foo', baz: 'foo', systemDate: new java.sql.Date(new Date().getTime())]
     *
     *     assert generator.toJson(input) == '{"lastUpdated":"2014"}'
     * 
* * @since 2.5.0 */ class Options { protected static final String JSON_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ"; protected static final Locale JSON_DATE_FORMAT_LOCALE = Locale.US; protected static final String DEFAULT_TIMEZONE = "GMT"; protected boolean excludeNulls; protected boolean disableUnicodeEscaping; protected String dateFormat = JSON_DATE_FORMAT; protected Locale dateLocale = JSON_DATE_FORMAT_LOCALE; protected TimeZone timezone = TimeZone.getTimeZone(DEFAULT_TIMEZONE); protected final Set converters = new LinkedHashSet(); protected final Set excludedFieldNames = new HashSet(); protected final Set> excludedFieldTypes = new HashSet>(); public Options() {} /** * Do not serialize {@code null} values. * * @return a reference to this {@code Options} instance */ public Options excludeNulls() { excludeNulls = true; return this; } /** * Disables the escaping of Unicode characters in JSON String values. * * @return a reference to this {@code Options} instance */ public Options disableUnicodeEscaping() { disableUnicodeEscaping = true; return this; } /** * Sets the date format that will be used to serialize {@code Date} objects. * This must be a valid pattern for {@link java.text.SimpleDateFormat} and the * date formatter will be constructed with the default locale of {@link Locale#US}. * * @param format date format pattern used to serialize dates * @return a reference to this {@code Options} instance * @exception NullPointerException if the given pattern is null * @exception IllegalArgumentException if the given pattern is invalid */ public Options dateFormat(String format) { return dateFormat(format, JSON_DATE_FORMAT_LOCALE); } /** * Sets the date format that will be used to serialize {@code Date} objects. * This must be a valid pattern for {@link java.text.SimpleDateFormat}. * * @param format date format pattern used to serialize dates * @param locale the locale whose date format symbols will be used * @return a reference to this {@code Options} instance * @exception IllegalArgumentException if the given pattern is invalid */ public Options dateFormat(String format, Locale locale) { // validate date format pattern new SimpleDateFormat(format, locale); dateFormat = format; dateLocale = locale; return this; } /** * Sets the time zone that will be used to serialize dates. * * @param timezone used to serialize dates * @return a reference to this {@code Options} instance * @exception NullPointerException if the given timezone is null */ public Options timezone(String timezone) { this.timezone = TimeZone.getTimeZone(timezone); return this; } /** * Registers a converter that will be called when a type it handles is encountered. * * @param converter to register * @return a reference to this {@code Options} instance */ public Options addConverter(Converter converter) { if (converter != null) { converters.add(converter); } return this; } /** * Registers a closure that will be called when the specified type or subtype * is serialized. * *

The closure must accept either 1 or 2 parameters. The first parameter * is required and will be instance of the {@code type} for which the closure * is registered. The second optional parameter should be of type {@code String} * and, if available, will be passed the name of the key associated with this * value if serializing a JSON Object. This parameter will be {@code null} when * serializing a JSON Array or when there is no way to determine the name of the key. * *

* Example: *


         *     def generator = new groovy.json.JsonGenerator.Options()
         *                         .addConverter(URL) { URL u {@code ->}
         *                             u.getHost()
         *                         }
         *                         .build()
         *
         *     def input = [domain: new URL('http://groovy-lang.org/json.html#_parser_variants')]
         *
         *     assert generator.toJson(input) == '{"domain":"groovy-lang.org"}'
         * 
* *

If two or more closures are registered for the exact same type the last * closure based on the order they were specified will be used. When serializing an * object its type is compared to the list of registered types in the order they were * given and the closure for the first suitable type will be called. Therefore, it is * important to register more specific types first. * * @param type the type to convert * @param closure called when the registered type or any type assignable to the given * type is encountered * @param the type this converter is registered to handle * @return a reference to this {@code Options} instance * @exception NullPointerException if the given type or closure is null * @exception IllegalArgumentException if the given closure does not accept * a parameter of the given type */ public Options addConverter(Class type, @ClosureParams(value=FromString.class, options={"T","T,String"}) Closure closure) { Converter converter = new DefaultJsonGenerator.ClosureConverter(type, closure); converters.remove(converter); return addConverter(converter); } /** * Excludes from the output any fields that match the specified names. * * @param fieldNames name of the field to exclude from the output * @return a reference to this {@code Options} instance */ public Options excludeFieldsByName(CharSequence... fieldNames) { return excludeFieldsByName(Arrays.asList(fieldNames)); } /** * Excludes from the output any fields that match the specified names. * * @param fieldNames collection of names to exclude from the output * @return a reference to this {@code Options} instance */ public Options excludeFieldsByName(Iterable fieldNames) { for (CharSequence cs : fieldNames) { if (cs != null) { excludedFieldNames.add(cs.toString()); } } return this; } /** * Excludes from the output any fields whose type is the same or is * assignable to any of the given types. * * @param types excluded from the output * @return a reference to this {@code Options} instance */ public Options excludeFieldsByType(Class... types) { return excludeFieldsByType(Arrays.asList(types)); } /** * Excludes from the output any fields whose type is the same or is * assignable to any of the given types. * * @param types collection of types to exclude from the output * @return a reference to this {@code Options} instance */ public Options excludeFieldsByType(Iterable> types) { for (Class c : types) { if (c != null) { excludedFieldTypes.add(c); } } return this; } /** * Creates a {@link JsonGenerator} that is based on the current options. * * @return a fully configured {@link JsonGenerator} */ public JsonGenerator build() { return new DefaultJsonGenerator(this); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy