Implement your own object binder for Route paramet

2019-04-08 14:12发布

问题:

Well, I want to replace my String param from the following Play scala Route into my own object, say "MyObject"

 From GET /api/:id  controllers.MyController.get(id: String)

 To GET /api/:id  controllers.MyController.get(id: MyOwnObject)

Any idea on how to do this would be appreciated.

回答1:

Use PathBindable to bind parameters from path rather than from query. Sample implementation for binding ids from path separated by comma (no error handling):

public class CommaSeparatedIds implements PathBindable<CommaSeparatedIds> {

    private List<Long> id;

    @Override
    public IdBinder bind(String key, String txt) {
        if ("id".equals(key)) {
            String[] split = txt.split(",");
            id = new ArrayList<>(split.length + 1);
            for (String s : split) {
                    long parseLong = Long.parseLong(s);
                    id.add(Long.valueOf(parseLong));
            }
            return this;
        }
        return null;
    }

    ...

}

Sample path:

/data/entity/1,2,3,4

Sample routes entry:

GET /data/entity/:id    controllers.EntityController.process(id: CommaSeparatedIds)


回答2:

Well, I have written up my own "MyOwnObject" binder now. Another way of implementing PathBindable to bind an object.

object Binders {
  implicit def pathBinder(implicit intBinder: PathBindable[String]) = new PathBindable[MyOwnObject] {
  override def bind(key: String, value: String): Either[String, MyOwnObject] = {
  for {
    id <- intBinder.bind(key, value).right
  } yield UniqueId(id)
 }

 override def unbind(key: String, id: UniqueId): String = {
  intBinder.unbind(key, id.value)
 }
}
}


回答3:

I'm not sure if it works for binding data in the path part of a URL, but you may want to read the docs on QueryStringBindable if you're able to accept your data as query params.