Class Converter

java.lang.Object
com.cedarsoftware.util.Converter

public final class Converter extends Object
Instance conversion utility for converting objects between various types.

Supports conversion from primitive types to their corresponding wrapper classes, Number classes, Date and Time classes (e.g., Date, Timestamp, LocalDate, LocalDateTime, ZonedDateTime, Calendar), BigInteger, BigDecimal, Atomic classes (e.g., AtomicBoolean, AtomicInteger, AtomicLong), Class, UUID, String, Collection classes (e.g., List, Set, Map), ByteBuffer, CharBuffer, and other related classes.

The Converter includes thousands of built-in conversions. Use the getSupportedConversions() API to view all source-to-target conversion mappings.

The primary API is convert(Object, Class). For example:


     Long x = convert("35", Long.class);
     Date d = convert("2015/01/01", Date.class);
     int y = convert(45.0, int.class);
     String dateStr = convert(date, String.class);
     String dateStr = convert(calendar, String.class);
     Short t = convert(true, short.class);     // returns (short) 1 or 0
     Long time = convert(calendar, long.class); // retrieves calendar's time as long
     Map<String, Object> map = Map.of("_v", "75.0");
     Double value = convert(map, double.class); // Extracts "_v" key and converts it
 

Null Handling: If a null value is passed as the source, the Converter returns:

  • null for object types
  • 0 for numeric primitive types
  • false for boolean primitives
  • '' for char primitives

Map Conversions: A Map can be converted to almost all supported JDK data classes. For example, UUID can be converted to/from a Map with keys like "mostSigBits" and "leastSigBits". Date/Time classes expect specific keys such as "time" or "nanos". For other classes, the Converter typically looks for a "value" key to source the conversion.

Extensibility: Additional conversions can be added by specifying the source class, target class, and a conversion function (e.g., a lambda). Use the addConversion(Class, Class, Convert) method to register custom converters. This allows for the inclusion of new Collection types and other custom types as needed.

Supported Collection Conversions: The Converter supports conversions involving various Collection types, including but not limited to:

These conversions facilitate seamless transformation between different Collection types and other supported classes.

Usage Example:


     ConverterOptions options = new ConverterOptions();
     Converter converter = new Converter(options);

     // Convert String to Integer
     Integer number = converter.convert("123", Integer.class);

     // Convert Enum to String
     Day day = Day.MONDAY;
     String dayStr = converter.convert(day, String.class);

     // Convert Object[], String[], Collection, and primitive Arrays to EnumSet
     Object[] array = {Day.MONDAY, Day.WEDNESDAY, "FRIDAY", 4};
     EnumSet<Day> daySet = (EnumSet<Day>)(Object)converter.convert(array, Day.class);

     Enum, String, and Number value in the source collection/array is properly converted
     to the correct Enum type and added to the returned EnumSet. Null values inside the
     source (Object[], Collection) are skipped.

     When converting arrays or collections to EnumSet, you must use a double cast due to Java's
     type system and generic type erasure. The cast is safe as the converter guarantees return of
     an EnumSet when converting arrays/collections to enum types.

     // Add a custom conversion from String to CustomType
     converter.addConversion(String.class, CustomType.class, (from, conv) -> new CustomType(from));

     // Convert using the custom converter
     CustomType custom = converter.convert("customValue", CustomType.class);
 

Author:

John DeRegnaucourt ([email protected])
Copyright (c) Cedar Software LLC

Licensed 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

License

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.
  • Method Details

    • convert

      public static <T> T convert(Object from, Class<T> toType)
      Converts the given source object to the specified target type.

      The convert method serves as the primary API for transforming objects between various types. It supports a wide range of conversions, including primitive types, wrapper classes, numeric types, date and time classes, collections, and custom objects. Additionally, it allows for extensibility by enabling the registration of custom converters.

      Key Features:

      • Wide Range of Supported Types: Supports conversion between Java primitives, their corresponding wrapper classes, Number subclasses, date and time classes (e.g., Date, LocalDateTime), collections (e.g., List, Set, Map), UUID, and more.
      • Null Handling: Gracefully handles null inputs by returning null for object types, default primitive values (e.g., 0 for numeric types, false for boolean), and default characters.
      • Inheritance-Based Conversions: Automatically considers superclass and interface hierarchies to find the most suitable converter when a direct conversion is not available.
      • Custom Converters: Allows users to register custom conversion logic for specific source-target type pairs using the addConversion(Class, Class, Convert) method.
      • Thread-Safe: Designed to be thread-safe, allowing concurrent conversions without compromising data integrity.

      Usage Examples:

      
           ConverterOptions options = new ConverterOptions();
           Converter converter = new Converter(options);
      
           // Example 1: Convert String to Integer
           String numberStr = "123";
           Integer number = converter.convert(numberStr, Integer.class);
           System.out.println("Converted Integer: " + number); // Output: Converted Integer: 123
      
           // Example 2: Convert String to Date
           String dateStr = "2024-04-27";
           LocalDate date = converter.convert(dateStr, LocalDate.class);
           System.out.println("Converted Date: " + date); // Output: Converted Date: 2024-04-27
      
           // Example 3: Convert Enum to String
           Day day = Day.MONDAY;
           String dayStr = converter.convert(day, String.class);
           System.out.println("Converted Day: " + dayStr); // Output: Converted Day: MONDAY
      
           // Example 4: Convert Array to List
           String[] stringArray = {"apple", "banana", "cherry"};
           List<String> stringList = converter.convert(stringArray, List.class);
           System.out.println("Converted List: " + stringList); // Output: Converted List: [apple, banana, cherry]
      
           // Example 5: Convert Map to UUID
           Map<String, Object> uuidMap = Map.of("mostSigBits", 123456789L, "leastSigBits", 987654321L);
           UUID uuid = converter.convert(uuidMap, UUID.class);
           System.out.println("Converted UUID: " + uuid); // Output: Converted UUID: 00000000-075b-cd15-0000-0000003ade68
      
           // Example 6: Convert Object[], String[], Collection, and primitive Arrays to EnumSet
           Object[] array = {Day.MONDAY, Day.WEDNESDAY, "FRIDAY", 4};
           EnumSet<Day> daySet = (EnumSet<Day>)(Object)converter.convert(array, Day.class);
      
           Enum, String, and Number value in the source collection/array is properly converted
           to the correct Enum type and added to the returned EnumSet. Null values inside the
           source (Object[], Collection) are skipped.
      
           When converting arrays or collections to EnumSet, you must use a double cast due to Java's
           type system and generic type erasure. The cast is safe as the converter guarantees return of
           an EnumSet when converting arrays/collections to enum types.
      
           // Example 7: Register and Use a Custom Converter
           // Custom converter to convert String to CustomType
           converter.addConversion(String.class, CustomType.class, (from, conv) -> new CustomType(from));
      
           String customStr = "customValue";
           CustomType custom = converter.convert(customStr, CustomType.class);
           System.out.println("Converted CustomType: " + custom); // Output: Converted CustomType: CustomType{value='customValue'}
       
       

      Parameter Descriptions:

      • from: The source object to be converted. This can be any object, including null. The actual type of from does not need to match the target type; the Converter will attempt to perform the necessary transformation.
      • toType: The target class to which the source object should be converted. This parameter specifies the desired output type. It can be a primitive type (e.g., int.class), a wrapper class (e.g., Integer.class), or any other supported class.

      Return Value:

      Returns an instance of the specified target type toType, representing the converted value of the source object from. If from is null, the method returns:

      • null for non-primitive target types.
      • Default primitive values for primitive target types (e.g., 0 for numeric types, false for boolean, '' for char).

      Exceptions:

      • IllegalArgumentException: Thrown if the conversion from the source type to the target type is not supported, or if the target type toType is null.
      • RuntimeException: Any underlying exception thrown during the conversion process is propagated as a RuntimeException.

      Supported Conversions:

      The Converter supports a vast array of conversions, including but not limited to:

      Extensibility:

      Users can extend the Converter's capabilities by registering custom converters for specific type pairs. This is accomplished using the addConversion(Class, Class, Convert) method, which accepts the source type, target type, and a Convert functional interface implementation that defines the conversion logic.

      Performance Considerations:

      The Converter utilizes caching mechanisms to store and retrieve converters, ensuring efficient performance even with a large number of conversion operations. However, registering an excessive number of custom converters may impact memory usage. It is recommended to register only necessary converters to maintain optimal performance.

      Type Parameters:
      T - The type of the target object.
      Parameters:
      from - The source object to be converted. Can be any object, including null.
      toType - The target class to which the source object should be converted. Must not be null.
      Returns:
      An instance of toType representing the converted value of from.
      Throws:
      IllegalArgumentException - if toType is null or if the conversion is not supported.
      See Also:
    • isConversionSupportedFor

      public static boolean isConversionSupportedFor(Class<?> source, Class<?> target)
      Determines whether a conversion from the specified source type to the target type is supported. For array-to-array conversions, this method verifies that both array conversion and component type conversions are supported.

      The method checks three paths for conversion support:

      1. Direct conversions as defined in the conversion maps
      2. Collection/Array/EnumSet conversions - for array-to-array conversions, also verifies that component type conversions are supported
      3. Inherited conversions (via superclasses and implemented interfaces)

      For array conversions, this method performs a deep check to ensure both the array types and their component types can be converted. For example, when checking if a String[] can be converted to Integer[], it verifies both:

      • That array-to-array conversion is supported
      • That String-to-Integer conversion is supported for the components
      Parameters:
      source - The source class type
      target - The target class type
      Returns:
      true if the conversion is fully supported (including component type conversions for arrays), false otherwise
    • isDirectConversionSupported

      public static boolean isDirectConversionSupported(Class<?> source, Class<?> target)
      Determines whether a direct conversion from the specified source type to the target type is supported, without considering inheritance hierarchies. For array-to-array conversions, verifies that both array conversion and component type conversions are directly supported.

      The method checks:

      1. User-defined and built-in direct conversions
      2. Collection/Array/EnumSet conversions - for array-to-array conversions, also verifies that component type conversions are directly supported

      For array conversions, performs a deep check to ensure both the array types and their component types can be converted directly. For example, when checking if a String[] can be converted to Integer[], verifies both:

      • That array-to-array conversion is supported
      • That String-to-Integer conversion is directly supported
      Parameters:
      source - The source class type
      target - The target class type
      Returns:
      true if a direct conversion exists (including component type conversions for arrays), false otherwise
    • isSimpleTypeConversionSupported

      public static boolean isSimpleTypeConversionSupported(Class<?> source, Class<?> target)
      Determines whether a conversion from the specified source type to the target type is supported, excluding any conversions involving arrays or collections.

      The method is particularly useful when you need to verify that a conversion is possible between simple types without considering array or collection conversions. This can be helpful in scenarios where you need to validate component type conversions separately from their container types.

      Example usage:

      
       // Check if String can be converted to Integer
       boolean canConvert = Converter.isSimpleTypeConversionSupported(
           String.class, Integer.class);  // returns true
      
       // Check array conversion (always returns false)
       boolean arrayConvert = Converter.isSimpleTypeConversionSupported(
           String[].class, Integer[].class);  // returns false
      
       // Intentionally repeat source type (class) - will find identity conversion
       // Let's us know that it is a "simple" type (String, Date, Class, UUID, URL, Temporal type, etc.)
       boolean isSimpleType = Converter.isSimpleTypeConversionSupported(
           ZonedDateTime.class, ZonedDateTime.class);
      
       // Check collection conversion (always returns false)
       boolean listConvert = Converter.isSimpleTypeConversionSupported(
           List.class, Set.class);  // returns false
       
      Parameters:
      source - The source class type to check
      target - The target class type to check
      Returns:
      true if a non-collection conversion exists between the types, false if either type is an array/collection or no conversion exists
      See Also:
    • allSupportedConversions

      public static Map<Class<?>,Set<Class<?>>> allSupportedConversions()
      Retrieves a map of all supported conversions, categorized by source and target classes.

      The returned map's keys are source classes, and each key maps to a Set of target classes that the source can be converted to.

      Returns:
      A Map<Class<?>, Set<Class<?>>> representing all supported conversions.
    • getSupportedConversions

      public static Map<String,Set<String>> getSupportedConversions()
      Retrieves a map of all supported conversions with class names instead of class objects.

      The returned map's keys are source class names, and each key maps to a Set of target class names that the source can be converted to.

      Returns:
      A Map<String, Set<String>> representing all supported conversions by class names.
    • addConversion

      public static Convert<?> addConversion(Class<?> source, Class<?> target, Convert<?> conversionFunction)
      Adds a new conversion function for converting from one type to another. If a conversion already exists for the specified source and target types, the existing conversion will be overwritten.

      When convert(source, target) is called, the conversion function is located by matching the class of the source instance and the target class. If an exact match is found, that conversion function is used. If no exact match is found, the method attempts to find the most appropriate conversion by traversing the class hierarchy of the source and target types (including interfaces), excluding common marker interfaces such as Serializable, Comparable, and Cloneable. The nearest match based on class inheritance and interface implementation is used.

      This method allows you to explicitly define custom conversions between types. It also supports the automatic handling of primitive types by converting them to their corresponding wrapper types (e.g., int to Integer).

      Note: This method utilizes the ClassUtilities.toPrimitiveWrapperClass(Class) utility to ensure that primitive types are mapped to their respective wrapper classes before attempting to locate or store the conversion.

      Parameters:
      source - The source class (type) to convert from.
      target - The target class (type) to convert to.
      conversionFunction - A function that converts an instance of the source type to an instance of the target type.
      Returns:
      The previous conversion function associated with the source and target types, or null if no conversion existed.
    • convert2String

      public static String convert2String(Object fromInstance)
      Convert from the passed in instance to a String. If null is passed in, this method will return "". Call 'getSupportedConversions()' to see all conversion options for all Classes (all sources to all destinations).
    • convertToString

      public static String convertToString(Object fromInstance)
      Convert from the passed in instance to a String. If null is passed in, this method will return null.
    • convert2BigDecimal

      public static BigDecimal convert2BigDecimal(Object fromInstance)
      Convert from the passed in instance to a BigDecimal. If null or "" is passed in, this method will return a BigDecimal with the value of 0.
    • convertToBigDecimal

      public static BigDecimal convertToBigDecimal(Object fromInstance)
      Convert from the passed in instance to a BigDecimal. If null is passed in, this method will return null. If "" is passed in, this method will return a BigDecimal with the value of 0.
    • convert2BigInteger

      public static BigInteger convert2BigInteger(Object fromInstance)
      Convert from the passed in instance to a BigInteger. If null or "" is passed in, this method will return a BigInteger with the value of 0.
    • convertToBigInteger

      public static BigInteger convertToBigInteger(Object fromInstance)
      Convert from the passed in instance to a BigInteger. If null is passed in, this method will return null. If "" is passed in, this method will return a BigInteger with the value of 0.
    • convertToSqlDate

      public static Date convertToSqlDate(Object fromInstance)
      Convert from the passed in instance to a java.sql.Date. If null is passed in, this method will return null.
    • convertToTimestamp

      public static Timestamp convertToTimestamp(Object fromInstance)
      Convert from the passed in instance to a Timestamp. If null is passed in, this method will return null.
    • convertToDate

      public static Date convertToDate(Object fromInstance)
      Convert from the passed in instance to a Date. If null is passed in, this method will return null.
    • convertToLocalDate

      public static LocalDate convertToLocalDate(Object fromInstance)
      Convert from the passed in instance to a LocalDate. If null is passed in, this method will return null.
    • convertToLocalDateTime

      public static LocalDateTime convertToLocalDateTime(Object fromInstance)
      Convert from the passed in instance to a LocalDateTime. If null is passed in, this method will return null.
    • convertToZonedDateTime

      public static ZonedDateTime convertToZonedDateTime(Object fromInstance)
      Convert from the passed in instance to a Date. If null is passed in, this method will return null.
    • convertToCalendar

      public static Calendar convertToCalendar(Object fromInstance)
      Convert from the passed in instance to a Calendar. If null is passed in, this method will return null.
    • convert2char

      public static char convert2char(Object fromInstance)
      Convert from the passed in instance to a char. If null is passed in, (char) 0 is returned.
    • convertToCharacter

      public static Character convertToCharacter(Object fromInstance)
      Convert from the passed in instance to a Character. If null is passed in, null is returned.
    • convert2byte

      public static byte convert2byte(Object fromInstance)
      Convert from the passed in instance to a byte. If null is passed in, (byte) 0 is returned.
    • convertToByte

      public static Byte convertToByte(Object fromInstance)
      Convert from the passed in instance to a Byte. If null is passed in, null is returned.
    • convert2short

      public static short convert2short(Object fromInstance)
      Convert from the passed in instance to a short. If null is passed in, (short) 0 is returned.
    • convertToShort

      public static Short convertToShort(Object fromInstance)
      Convert from the passed in instance to a Short. If null is passed in, null is returned.
    • convert2int

      public static int convert2int(Object fromInstance)
      Convert from the passed in instance to an int. If null is passed in, (int) 0 is returned.
    • convertToInteger

      public static Integer convertToInteger(Object fromInstance)
      Convert from the passed in instance to an Integer. If null is passed in, null is returned.
    • convert2long

      public static long convert2long(Object fromInstance)
      Convert from the passed in instance to an long. If null is passed in, (long) 0 is returned.
    • convertToLong

      public static Long convertToLong(Object fromInstance)
      Convert from the passed in instance to a Long. If null is passed in, null is returned.
    • convert2float

      public static float convert2float(Object fromInstance)
      Convert from the passed in instance to a float. If null is passed in, 0.0f is returned.
    • convertToFloat

      public static Float convertToFloat(Object fromInstance)
      Convert from the passed in instance to a Float. If null is passed in, null is returned.
    • convert2double

      public static double convert2double(Object fromInstance)
      Convert from the passed in instance to a double. If null is passed in, 0.0d is returned.
    • convertToDouble

      public static Double convertToDouble(Object fromInstance)
      Convert from the passed in instance to a Double. If null is passed in, null is returned.
    • convert2boolean

      public static boolean convert2boolean(Object fromInstance)
      Convert from the passed in instance to a boolean. If null is passed in, false is returned.
    • convertToBoolean

      public static Boolean convertToBoolean(Object fromInstance)
      Convert from the passed in instance to a Boolean. If null is passed in, null is returned.
    • convert2AtomicInteger

      public static AtomicInteger convert2AtomicInteger(Object fromInstance)
      Convert from the passed in instance to an AtomicInteger. If null is passed in, a new AtomicInteger(0) is returned.
    • convertToAtomicInteger

      public static AtomicInteger convertToAtomicInteger(Object fromInstance)
      Convert from the passed in instance to an AtomicInteger. If null is passed in, null is returned.
    • convert2AtomicLong

      public static AtomicLong convert2AtomicLong(Object fromInstance)
      Convert from the passed in instance to an AtomicLong. If null is passed in, new AtomicLong(0L) is returned.
    • convertToAtomicLong

      public static AtomicLong convertToAtomicLong(Object fromInstance)
      Convert from the passed in instance to an AtomicLong. If null is passed in, null is returned.
    • convert2AtomicBoolean

      public static AtomicBoolean convert2AtomicBoolean(Object fromInstance)
      Convert from the passed in instance to an AtomicBoolean. If null is passed in, new AtomicBoolean(false) is returned.
    • convertToAtomicBoolean

      public static AtomicBoolean convertToAtomicBoolean(Object fromInstance)
      Convert from the passed in instance to an AtomicBoolean. If null is passed in, null is returned.
    • localDateToMillis

      @Deprecated public static long localDateToMillis(LocalDate localDate)
      Deprecated.
      No longer needed - use convert(localDate, long.class)
      Parameters:
      localDate - A Java LocalDate
      Returns:
      a long representing the localDate as epoch milliseconds (since 1970 Jan 1 at midnight)
    • localDateTimeToMillis

      @Deprecated public static long localDateTimeToMillis(LocalDateTime localDateTime)
      Deprecated.
      No longer needed - use convert(localDateTime, long.class)
      Parameters:
      localDateTime - A Java LocalDateTime
      Returns:
      a long representing the localDateTime as epoch milliseconds (since 1970 Jan 1 at midnight)
    • zonedDateTimeToMillis

      @Deprecated public static long zonedDateTimeToMillis(ZonedDateTime zonedDateTime)
      Deprecated.
      No longer needed - use convert(ZonedDateTime, long.class)
      Parameters:
      zonedDateTime - A Java ZonedDateTime
      Returns:
      a long representing the ZonedDateTime as epoch milliseconds (since 1970 Jan 1 at midnight)