我正在Play 2.1中构建一个JSON RPC。为了调用正确的方法,RPC调度程序使用反射按名称创建和调用类方法实例。
现在RPC方法如下:
def create(obj: JsValue) = {
val menu: Menu = Json.fromJson[Menu](obj).get
collection.insert(menu).map( r => toDirectResult(r))
}
def createCustom(obj: JsValue) = {
val menu: Menu = Json.fromJson(obj)(Menu.customFormat).get
collection.insert(menu).map( r => toDirectResult(r))
}
我想做的是能够定义这样的RPC方法:
def create(menu: Menu) = {
collection.insert(menu).map( r => toDirectResult(r))
}
问题是,RPC调度程序只在运行时知道必须在名为"Menus"的类上调用名为"create"的方法,并且它具有要作为JsValue传递给该方法的参数值。通过反射,我可以找到RPC方法的参数数量及其类型。当参数类型是case类时,如何使用case类的伴随对象中定义的隐式Formatter(或Reader)将JsValue转换为case类实例?
对于createCustom方法,我意识到没有"神奇"的解决方案,但自从我开始学习Scala以来,我发现用这种编程语言几乎没有什么是真正不可能的。是否可以使用注释或类似的东西来指定非隐式的格式化程序?
您需要实现一个PathBinder。。。这应该有帮助http://www.richard-foy.fr/blog/2012/04/09/how-to-implement-a-custom-pathbindable-with-play-2/
经过进一步的仔细考虑,我决定反射确实不是解决我问题的正确方法。它在编译时缺乏类型安全性和正确的错误报告,更难调试,也会影响性能。实际上,我已经掌握了在构建时生成代码所需的所有信息。
不幸的是,我无法使用Play路由器,因为对于JSON RPC调度器来说,路由取决于请求体,而在Play路由过程中,请求体不可用。但从本质上讲,RPC调度器所做的事情与Play路由器相同。所以现在我只想手动编码我的RPC路由,然后问题就解决了。在未来,我计划编写一个SBT插件,它将自动生成调度器代码,类似于Play路由器。