Статьи

Используйте JSON с Play и Scala

Когда вы начинаете набирать код scala с помощью play, первое, что приходит на ум, — это JSON. Без сомнения, JSON является одним из самых основных компонентов веб-приложений. Остальные apis используют json, ваше угловое приложение должно использовать json, и этот список можно продолжить.

Если вы ленивы, как я, вы ожидаете, что достаточно просто передать обратно объекты scala через ваш контроллер или указать класс scala в качестве аргумента для вашего контроллера. Каким-то образом все не так уж и далеко, однако необходимо внести некоторые коррективы.

Первый шаг — указать модуль json.

1
libraryDependencies += json

Библиотека JSON очень похожа на библиотеку org.json для Java, но с дополнительными возможностями. Типы, которые мы имеем из коробки:

JsString
JsNumber
JsBoolean
JsObject
JsArray
JsNull

Однако ключевая функциональность обеспечивается преобразователями Reads и Writes, которые можно использовать для упорядочивания или разархивирования наших структур данных.

Предположим, у нас есть класс с именем User

1
case class User(id:Option[Long],email:String,firstName:String,lastName:String)

Мы хотим использовать этот класс для передачи данных на наши контроллеры или использовать их в качестве ответа после завершения нашего действия.

Таким образом, нам нужно создать Reader и Writer для объекта User.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
implicit val userWrites = new Writes[User] {
    def writes(user: User) = Json.obj(
      "id" -> user.id,
      "email" -> user.email,
      "firstName" -> user.firstName,
      "lastName" -> user.lastName
    )
  }
 
  implicit val userReads: Reads[User] = (
    (__ \ "id").readNullable[Long] and
      (__ \ "email").read[String] and
      (__ \ "firstName").read[String] and
      (__ \ "lastName").read[String]
    )(User.apply _)

Скорее всего, вы заметили, что идентификатор не является обязательным. Мы делаем это для того, чтобы иметь возможность передать идентификатор пользователя или нет.

Теперь давайте соединим их в контроллере.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package controllers
 
import javax.inject.Inject
 
import com.google.inject.Singleton
import play.api.libs.json._
import play.api.mvc.{Action, Controller}
import play.api.libs.functional.syntax._
 
/**
  * Created by gkatzioura on 4/26/17.
  */
case class User(id:Option[Long],email:String,firstName:String,lastName:String)
 
@Singleton
class UserController @Inject() extends Controller {
 
  def all = Action { implicit request =>
    val users = Seq(
      User(Option(1L),"[email protected]","Emmanouil","Gkatziouras"),
      User(Option(2L),"[email protected]","John","Doe"),
      User(Option(3L),"[email protected]","John2","Doe2")
    )
    Ok(Json.toJson(users))
  }
 
  def greet = Action
 
  def add = Action { implicit request =>
 
    val user  = Json.fromJson[User](request.body.asJson.get).get
    val newUser = User(Option(4L),user.email,user.firstName,user.lastName)
    Ok(Json.toJson(newUser))
  }
 
  implicit val userWrites = new Writes[User] {
    def writes(user: User) = Json.obj(
      "id" -> user.id,
      "email" -> user.email,
      "firstName" -> user.firstName,
      "lastName" -> user.lastName
    )
  }
 
  implicit val userReads: Reads[User] = (
    (__ \ "id").readNullable[Long] and
      (__ \ "email").read[String] and
      (__ \ "firstName").read[String] and
      (__ \ "lastName").read[String]
    )(User.apply _)
}

А также конфигурация корней

1
2
GET     /user/                   controllers.UserController.all
POST    /user/                   controllers.UserController.add

Как мы видим, метод all возвращает список пользовательских объектов в формате Json, а метод add должен сохранять пользовательский объект и присваивать ему идентификатор.

Давайте сделаем запрос curl и проверим наши результаты

01
02
03
04
05
06
07
08
09
10
11
curl http://localhost:9000/user/
 
....
 
[{"id":1,"email":"[email protected]","firstName":"Emmanouil","lastName":"Gkatziouras"},{"id":2,"email":"[email protected]","firstName":"John","lastName":"Doe"},{"id":3,"email":"[email protected]","firstName":"John2","lastName":"Doe2"}]
 
curl -H "Content-Type: application/json" -X POST -d '{"email":"[email protected]","firstName":"Emmanouil","lastName":"Gkatziouras"}' http://localhost:9000/user/
 
...
 
{"id":4,"email":"[email protected]","firstName":"Emmanouil","lastName":"Gkatziouras"}

Поэтому мы не занимались специальной обработкой или чтением json, а использовали только объекты. Это оно! Теперь вы готовы к новым действиям, связанным с JSON!

Вы можете проверить исходный код на GitHub .

Ссылка: Используйте JSON с Play и Scala от нашего партнера по JCG Эммануила Гкациоураса в блоге gkatzioura .