Reputation: 1925
I have a scenario where I have different types of dates coming, in that case the existing spring conversion is failing as vales coming are in different formats.
Is there a way I can make Spring use my custom DateFormatter ?
Upvotes: 0
Views: 991
Reputation: 8307
Is there a way I can make Spring use my custom DateFormatter ?
Yes but as your use case is specific I believe it is better to use a custom annotation to make everything explicit.
These interface
s can be used to accomplish this task:
These classes source code can be used as a reference:
Jsr310DateTimeFormatAnnotationFormatterFactory
DateTimeFormatAnnotationFormatterFactory
NumberFormatAnnotationFormatterFactory
You could do something like this:
UnstableDateFormats
annotation@Retention(RUNTIME)
public @interface UnstableDateFormats {
String[] formatsToTry();
}
Formatter
implementationpublic class UnstableDateFormatter implements Formatter<LocalDate> {
private final List<String> formatsToTry;
public UnstableDateFormatter(List<String> formatsToTry) {
this.formatsToTry = formatsToTry;
}
@Override
public LocalDate parse(String text, Locale locale) throws ParseException {
for (String format : formatsToTry) {
try {
return LocalDate.parse(text, DateTimeFormatter.ofPattern(format));
} catch (DateTimeParseException ignore) {
// or log the exception
}
}
throw new IllegalArgumentException("Unable to parse \"" + text
+ "\" as LocalDate using formats = " + String.join(", ", formatsToTry));
}
@Override
public String print(LocalDate object, Locale locale) {
// Implement this method thoroughly
// If you're accepting dates in different formats which one should be used to print the value?
return object.toString();
}
}
AnnotationFormatterFactory
implementationpublic class UnstableDateFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<UnstableDateFormats> {
@Override
public Set<Class<?>> getFieldTypes() {
return Collections.singleton(LocalDate.class);
}
@Override
public Printer<?> getPrinter(UnstableDateFormats annotation, Class<?> fieldType) {
return new UnstableDateFormatter(Arrays.asList(annotation.formatsToTry()));
}
@Override
public Parser<?> getParser(UnstableDateFormats annotation, Class<?> fieldType) {
return new UnstableDateFormatter(Arrays.asList(annotation.formatsToTry()));
}
}
Don't forget to register the AnnotationFormatterFactory
implementation:
If you are using spring mvc you can do it in the web configuration (see Type Conversion):
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatterForFieldAnnotation(new UnstableDateFormatAnnotationFormatterFactory());
}
}
See also:
You may also want to consider:
Upvotes: 2