JAVA Spring

Spring Type Conversion & Formatter

neal89 2025. 4. 11. 14:51

1. Why Type Conversion Matters in Spring

Spring often needs to convert data types between String ↔ Object, especially in:

  • @RequestParam, @PathVariable, @ModelAttribute
  • YAML (@Value)
  • View rendering (Thymeleaf)
  • Form input/output

2. Converter Interface

public interface Converter<S, T> {
    T convert(S source);
}
  • Generic, bidirectional type conversion (e.g. String ↔ Integer, IpPort ↔ String)
  • Used programmatically or injected into Spring's type system

3. ConversionService

conversionService.convert("10", Integer.class); // returns 10
  • Central API for runtime type conversion
  • Main implementation: DefaultConversionService

ISP (Interface Segregation Principle)

Clients should not depend on methods they do not use.

  • DefaultConversionService implements both:
    • ConversionService: For type conversion
    • ConverterRegistry: For registering converters

This design separates usage from registration, following ISP.


4. Registering Converters via WebMvcConfigurer

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new StringToIpPortConverter());
        registry.addConverter(new IpPortToStringConverter());
    }
}

These converters are then automatically applied in @RequestParam, @PathVariable, etc.


5. Formatter Interface

public interface Formatter<T> extends Printer<T>, Parser<T> {
    String print(T object, Locale locale);
    T parse(String text, Locale locale);
}
  • Specialization of Converter for String ↔ Object with Locale support
  • Used for formatting numbers, dates, etc.
  • Example: "1,000" ↔ 1000

6. Registering Formatters: FormattingConversionService

⚠️ Note: ConversionService cannot accept formatters.

✅ Use FormattingConversionService (or its subclass DefaultFormattingConversionService) to register formatters.

conversionService.addFormatter(new MyNumberFormatter());
  • Internally, it adapts Formatter to Converter using the Adapter Pattern.
  • This allows uniform access to all converters/formatters through the ConversionService interface.

7. Built-in Formatter Annotations

Annotation Description

@NumberFormat Controls number formatting (e.g., #,###)
@DateTimeFormat Controls date/time formatting

Example:

@NumberFormat(pattern = "###,###")
private Integer number;

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime localDateTime;

8. Thymeleaf & Conversion

  • ${object} → plain output
  • ${{object}} → applies ConversionService for formatting

Works for both converters and formatters.


9. ❗ Not Applied: HttpMessageConverter

Spring's ConversionService is not used in:

  • JSON (de)serialization via HttpMessageConverter (uses Jackson/Gson)
  • To customize JSON formats (e.g., for numbers or dates), configure the JSON library directly.

✅ Final Takeaway

Concept Use Case
Converter General-purpose conversion between any two types
Formatter Locale-aware String ↔ Object formatting
ConversionService Unified API to perform conversions
FormattingConversionService Registers both converters and formatters (uses adapter pattern)
WebMvcConfigurer Hook to register your converters/formatters in Spring MVC
@NumberFormat / @DateTimeFormat Field-level formatting in models
Not Used In JSON serialization (handled by Jackson, not ConversionService)