Reputation: 51
I have a class that extends RestHelper to serve items in both xml and json. Currently, I am implementing the "serve"-method to return the entities in xml:
object Rest extends RestHelper {
serve {
case "supplier" :: "findAll" :: _ XmlGet _
=> supplierListToXml(Supplier.findAll)
}
def supplierListToXml(suppliers : List[Supplier]) = {
<suppliers>{suppliers.mapConserve(f=> f.toXml)}</suppliers>
}
}
I want to serve the same items as json aswell, depending on the Accept-header, using the serveJx-method (explained in http://www.assembla.com/wiki/show/liftweb/REST_Web_Services).
The class Supplier implements Convertable, and I implemented a conversion-method within the Rest-class:
object RestApi extends RestHelper {
implicit def cvt: JxCvtPF[Convertable] = {
case (JsonSelect, c, _) => c.toJson
case (XmlSelect, c, _) => c.toXml
}
serveJx {
case Get("2.0" :: "supplier" :: "head" :: _,_)
=> Full(Supplier.findAll.head)
}
}
... and this works find, when I serve a single supplier. But when I want to return a list of suppliers (List[Supplier]), the conversion-method cannot be applied.
case Get("2.0" :: "supplier" :: "findAll" :: _,_)
=> Full(Supplier.findAll.toList)
... and I get the compilation-error:
"could not find implicit value for parameter cvt:com.mycompany.api.RestApi.JxCvtPF[ScalaObject]"
Can someone please give me an example of how to modify the cvt-method to be able to convert list of convertables to a LiftResponse?
Cheers! /J
Upvotes: 0
Views: 552
Reputation: 51
I found a solution to the cvt-method. Change the type to implicit def cvt: JxCvtPF[Any] to be able to match specific classes. Then implement the list of convertables as such:
//Generic list templates
case (JsonSelect, c : List[Convertable], _) => JArray(for{item <- c} yield item.toJson)
case (XmlSelect, c : List[Convertable], _) => <list>{c.mapConserve(f => f.toXml)}</list>
Full solution:
object Rest extends RestHelper {
implicit def cvt: JxCvtPF[Any] = {
//Generic list templates
case (JsonSelect, c : List[Convertable], _) => JArray(for{item <- c} yield item.toJson)
case (XmlSelect, c : List[Convertable], _) => <list>{c.mapConserve(f => f.toXml)}</list>
//Single-items of convertable
case (JsonSelect, c : Convertable, _) => c.toJson
case (XmlSelect, c : Convertable, _) => c.toXml
}
serveJx {
case "supplier" :: "findAll" :: _ Get _
=> Full(Supplier.findAll)
case "channelPackage" :: "findAll" :: _ Get _
=> Full(ChannelPackage.findAll)
case "channelPackage" :: "findFromSupplierId" :: supplierId :: _ Get _
=> Full(Supplier.find(supplierId).head.channelPackages)
case "device" :: "findAll" :: _ Get _
=> Full(Device.findAll)
case "device" :: "findFromSupplierId" :: supplierId :: _ Get _
=> Full(Supplier.find(supplierId).head.devices)
}
}
Upvotes: 1