play 框架返回 json 类型

前言

play 框架返回 json 类型的数据,和 java 的区别较大。之前碰到了 model 转 json 结果为空的情况,这里做下简单的记录,供后来查询使用。
项目中,使用 slick 作为 FRM 框架集成方式。

问题

slick 查询返回的 model 实体类,需要转换为 json。

解决办法

方式一:通过 fastjson 转换。

通过 Alibaba 的 fastjson 来进行转换的话,需要额外使用 @BeanProperty 来注解所有字段,自动生成 get 和 set 方法,并且多个实体类不能放在同一个 class 中。这是由于 fastjson 是使用 java 的 get set 方法来获取字段的, scala 的 get 和 set 方法不同于 java 。
个人觉得使用 @BeanProperty 注解所有字段太麻烦了,寻找是否有一种更加优雅的方式,将 model 转为 json。

方式二:通过 play 自带的 Json 来转换。 推荐方式

首先,需要在返回类的伴生对象中,定义隐式转换。


 导包:import play.api.libs.json._
 
 定义隐式转换:
implicit val format: Format[Company] = Json.format[Company]

然后就可以在 controller 中,使用 Ok(Json.toJson(slickService.getCompany(id).get))进行转换了。

代码详见:
定义 Company model:

import play.api.libs.json._

case class Company(id: Long, businessCode: String, location: String, name: String, significance: String)

object Company {
  implicit val format: Format[Company] = Json.format[Company]
}

controller 调用转换:

class SlickController @Inject()(cc: ControllerComponents, slickService: ISlickService) extends AbstractController(cc) {

  def getCompany(id: Long) = Action {
    /**
     * 返回 json 类型的数据。
     * 两种方式:
     * 方式一: 手动实现 隐式转换 writes[Company]
     * 方式二: 在伴生对象中,添加 对应的 format ,然后调用 Json.toJson 转换    推荐方式
     */
    Ok(Json.toJson(slickService.getCompany(id).get))
  }

  /**
   * json data format
   * {
      "id": 5,
      "businessCode": "123456-03",
      "location": "北京",
      "significance": "IMPORTANT",
      "name": "百度公司"
     }
   */
  
  // 手动实现 writes[Company],要写出类型,不然 idea 不识别
  // model to a JsValue
  // 使用 Json.obj 和 Json.arr 来实例化
/**
  implicit val companyWrites: Writes[Company] = (company: Company) => {
    Json.obj(
      "id" -> company.id,
      "businessCode" -> company.businessCode,
      "location" -> company.location,
      "significance" -> company.significance,
      "name" -> company.name,
    )
  }
*/
  // 另一种写法 原生写法
  /**

  implicit val companyWrites_v2: Writes[Company] = (
    (JsPath \ "id").write[Long]
      .and((JsPath \ "businessCode").write[String])
      .and((JsPath \ "businessCode").write[String])
      .and((JsPath \ "businessCode").write[String])
      .and((JsPath \ "name").write[String])
    ) (unlift(Company.unapply))

  */

  // implicit JsValue to a model
  implicit val companyReads: Reads[Company] = (
    (JsPath \ "id").read[Long] and
      (JsPath \ "businessCode").read[String] and
      (JsPath \ "location").read[String] and
      (JsPath \ "significance").read[String] and
      (JsPath \ "name").read[String]
    ) (Company.apply _)
}

这里,在 slick 中,有一个小坑,由于在 case class 的伴生对象中,手动定义了隐式转换,就不能直接使用 case class 的 tupled 方法了,需要使用 (Company.apply _).tupled这种语法。

  class CompanyTable(tag: Tag) extends Table[Company](tag, "company") {

    val id: Rep[Long] = column[Long]("id", O.PrimaryKey, O.AutoInc, O.Unique)

    val business_code = column[String]("business_code")
    val location = column[String]("location")
    val name = column[String]("name")
    val significance = column[String]("significance")

  // https://scala-slick.org/doc/3.3.3/schemas.html 存在伴生对象时,需要这么限定
    override def * : ProvenShape[Company] = (id, business_code, location, name, significance) <> ((Company.apply _).tupled, Company.unapply)
  }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值