0

How do I create a custom type converter for a boolean parameter in a GET request?

For example, I want the allowed values in the GET request to be "oui" and "non" instead of "true" and "false". I followed the Spring documentation on how to do this, and tried the following:

@RestController
public class ExampleController {
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Boolean.class, new CustomBooleanEditor("oui", "non", true));
    }

    @GetMapping("/e")
    ResponseEntity<String> showRequestParam(@RequestParam boolean flag) {
        return new ResponseEntity<>(String.valueOf(flag), HttpStatus.OK);
    }
}

I also tried this:

@RestController
public class DemoController {
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.addCustomFormatter(new Formatter<Boolean>() {
            @Override
            public Boolean parse(String text, Locale locale) throws ParseException {
                if ("oui".equalsIgnoreCase(text)) return true;
                if ("non".equalsIgnoreCase(text)) return false;
                throw new ParseException("Invalid boolean parameter value '" + text + "'; please specify oui or non", 0);
            }

            @Override
            public String print(Boolean object, Locale locale) {
                return String.valueOf(object);
            }
        }, Boolean.class);
    }

    @GetMapping("/r")
    ResponseEntity<String> showRequestParam(@RequestParam(value = "param") boolean param) {
        return new ResponseEntity<>(String.valueOf(param), HttpStatus.OK);
    }
}

Neither of these worked. When supplying the value "oui", I got an HTTP 400 response with the following message:

Failed to convert value of type 'java.lang.String' to required type 'boolean'; nested exception is java.lang.IllegalArgumentException: Invalid boolean value [oui]"

Update:

I've also now tried using a Converter:

@Component
public class BooleanConverter implements Converter<String, Boolean> {
    @Override
    public Boolean convert(String text) {
        if ("oui".equalsIgnoreCase(text)) return true;
        if ("non".equalsIgnoreCase(text)) return false;
        throw new IllegalArgumentException("Invalid boolean parameter value '" + text + "'; please specify oui or non");
    }
}

This "kind of" works, in that it now accepts "oui" and "non", but it does so in addition to "true" and "false". How can I get it to accept "oui" and "non" instead of "true" and "false"?

k314159
  • 5,051
  • 10
  • 32
  • 1
    Does this answer your question? [How to convert spring-boot request parameter](https://stackoverflow.com/questions/52557076/how-to-convert-spring-boot-request-parameter) – Turing85 Nov 22 '22 at 17:04
  • @Turing85 no, it doesn't _quite_ answer it. See my update above. – k314159 Nov 22 '22 at 17:39
  • You can just add the cases for `true` and `false`. – Turing85 Nov 22 '22 at 17:39
  • @Turing85 unfortunately I haven't got a Github account, but the application is trivial. It contains no more code than is shown above. I just created a Spring Boot app using the initializer, added the code above, and all done in 5 minutes. – k314159 Nov 22 '22 at 17:46
  • And it takes about 2 minutes to create a github account :). And as I said: you can just add cases for `true` and `false`. – Turing85 Nov 22 '22 at 17:47
  • @Turing85 I don't see how I can add the cases for "true" and "false". Where? In the Converter? That doesn't get called at all if the string matches what's already allowed by default (which is "true", "1", "yes", "on", "false", "0", "no", and "off"). – k314159 Nov 22 '22 at 17:50
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/249814/discussion-between-turing85-and-k314159). – Turing85 Nov 22 '22 at 17:50

2 Answers2

2

In your first case, your requestParam is a boolean but you bind a Boolean.

I've tried with this code

@InitBinder
protected void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(Boolean.class, new CustomBooleanEditor("oui", "non", true));
}

@GetMapping("/e")
ResponseEntity<String> showRequestParam(@RequestParam(value="flag") Boolean flag) {
    return new ResponseEntity<>(String.valueOf(flag), HttpStatus.OK);
}

And it's print

true

when I call localhost:8080/e?flag=oui

Noplopy
  • 51
  • 3
1

can't you map it to an enum?

enum BooleanInput {
    oui(true),
    non(false);

    private boolean value;

    BooleanInput(boolean value) {
        this.value = value;
    }

    Boolean value() {
        return this.value;
    }
}

and in the controller,

    @GetMapping("/e")
    ResponseEntity<String> showRequestParam(@RequestParam BooleanInput flag) {
        return new ResponseEntity<>(flag.value(), HttpStatus.OK);
    }
sanurah
  • 976
  • 1
  • 6
  • 16