Reputation: 187
I know there are a lot of topics on this area already but none of them had a satisfying answer for me. I have the following endpoint and enum:
@RestController
public class MyController {
@PostMapping
public void doStuff(@RequestParam MyEnum myEnum){
...
}
}
public enum MyEnum {
PROPERTY_A("foo"),
PROPERTY_B("bar");
private String name;
MyEnum(String name) {
this.name = name;
}
}
I want to register a custom converter that converts the string values of foo and bar into the correct enum values of PROPERTY_A, PROPERTY_B. Something that should be easily solved with a simple @Override somewhere to hijack the standard converter that fails to convert this, yet all the answers I've seen for this question requires you to register code in three-four places which is not a satisfactory answer to the problem.
Upvotes: 0
Views: 294
Reputation: 28968
should be easily solved with a simple
@Override
somewhere to hijack the standard converter
If by saying standard converter, you refer to the MyEnum.valueOf(String)
method, then the answer is you can't.
Because method valueOf()
is static
and there's no concept of overriding for static
methods in Java. And more over the flavor valueOf(String)
is not even exists in the implicit parent class java.lang.Enum
, it gets added by the compiler as well as values()
method to every enum during the compilation.
In other words, you are not in control of valueOf(String)
method by any means.
register code in three-four places
Since your method doStuff()
expects an instance of MyEnum
and you didn't mention any other enum-classes, I assume that you are interested only in converting a string into a member of MyEnum
. And you can achieve this by adding a single method into MyEnum
(no need to introduce new code in multiple places):
public enum MyEnum {
PROPERTY_A("foo"),
PROPERTY_B("bar");
private String name;
MyEnum(String name) {
this.name = name;
}
public static MyEnum getByName(String name) {
return Arrays.stream(values())
.filter(e -> e.name.equals(name))
.findFirst()
.orElseThrow(); // throw NoSuchElementException if no constant with a matching property has been found
}
}
Method getByName()
will throw NoSuchElementException
if enum-member with the given name doesn't exist.
If you are not satisfied with such behavior, you can change the implementation. For instance, to return an optional object (which is more preferred than returning null
):
public static Optional<MyEnum> getByName(String name) {
return Arrays.stream(values())
.filter(e -> e.name.equals(name))
.findFirst();
}
Or you can use orElse()
instead of orElseThrow()
to return a particular enum-constant which would represent the absence of data, i.e. implement the Null-object pattern.
Upvotes: 1