Работа с JSON является очень распространенной задачей в процессе разработки программного обеспечения. В Scala вы можете сделать это разными способами, либо с помощью популярных библиотек Java, таких как Jackson, или с помощью специальных библиотек Scala. Как сделать правильный выбор из Spray JSON, Play JSON , Argonaut, Jackson, Rapture и многих других?
Однажды я получил тестовое задание на собеседовании. В соответствии с этим мне пришлось реализовать сериализацию и десериализацию JSON объекта Checkout в контексте электронной коммерции. Я проанализировал все существующие библиотеки JSON для Scala, я использовал каждую из них для небольших выборок и решил взять библиотеку Play JSON для этой задачи. Я сделал это, потому что у него есть исчерпывающая документация, много примеров, это часть самой популярной веб-платформы Scala, и мне нравится ее API.
Вопрос заключался в том, как использовать JSON-модуль PlayFramework без всего фреймворка. И я нашел отдельный репозиторий git с API Play JSON.
Для тех из вас, кто хочет увидеть, как использовать модуль Play JSON отдельно от Play Framework, я продолжу этот пост.
Как использовать модуль Play JSON?
Во-первых, вам нужно добавить библиотеку Play JSON в ваш проект. Вы можете сделать это различными способами — скачать код библиотеки и включить его в проект или использовать какой-либо инструмент управления зависимостями. Лично я использую SBT в проектах Scala.
Вот как мы можем добавить зависимость Play JSON в файл SBT:
|
1
2
3
4
5
6
7
|
name := "proectj-name"version := "1.0"scalaVersion := "2.11.7"libraryDependencies ++= Seq("com.typesafe.play" % "play-json_2.11" % "2.4.2") |
Тогда вы, вероятно, захотите посмотреть, как сериализация и десериализация JSON могут выполняться с помощью этой библиотеки. Что ж, давайте сделаем короткую демонстрацию. Вот модель JSON, и нам нужно работать с ней:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
{ "id": 1, "type": "credit card", "address": { "address1": "Baker str 3", "address2": "", "city": "London", "zipcode": "WC064" }, "token": "u4lPaa74M" "cvv": 112} |
Это часть модели Checkout — оплата. Что нам нужно сделать сначала, чтобы реализовать сериализацию и десериализацию для этой модели JSON?
- Создайте модель Scala для самой глубокой модели в JSON. Вот класс случая для поля Address:
12345
caseclassAddress(address1:String,address2:Option[String],city:String,state:String,zipcode:String) - Объявите правила записи и чтения , которые используются для записи модели Scala в JSON и для чтения JSON в Scala. Эта логика может быть объявлена в объекте Address:
010203040506070809101112131415
objectAddress {importplay.api.libs.json._implicitvaladdressFormats=Json.format[Address]defwriteAddress(address:Address)={Json.toJson(address)}defreadAddress(jsonAddress:JsValue)={jsonAddress.as[Address]}}Как видите, мы используем объект Play Json , чтобы выполнить сериализацию и десериализацию объекта с простыми полями. Под простыми я подразумеваю строки, числа, массивы и нулевые значения.
- Выполните действия № 1, № 2 для родительского объекта.
010203040506070809101112131415161718192021222324252627282930
caseclassPayment(id:Long,pType:String,address:Address,token:String,cvv:String)objectPayment {importplay.api.libs.json._defwritePayment(payment:Payment)={JsObject(Seq("id"-> JsNumber(payment.id),"type"-> JsString(payment.pType),"address"-> Json.toJson(payment.address),"token"-> JsString(payment.token),"cvv"-> JsString(payment.cvv)))}defreadPayment(jsonPayment:JsValue)={valid=(jsonPayment \"id").as[Long]valpType=(jsonPayment \"type").as[String]valaddress=(jsonPayment \"address").as[Address]valtoken=(jsonPayment \"token").as[String]valcvv=(jsonPayment \"cvv").as[String]Payment(id, pType, address, token, cvv)}}Мы получили более подробный код выше, это связано с именем поля типа . Поскольку слово типа зарезервировано в Scala, мы не можем использовать его как имя переменных в Scala. Таким образом, мы должны определить чтение и запись вручную для модели Payment.
Как проверить сериализацию и сериализацию в Scala?
Чтобы проверить, что все работает нормально, мы можем создать модульные тесты. Добавьте зависимость ScalaTest в файл SBT. Теперь это должно выглядеть так:
|
1
2
3
4
5
6
7
8
9
|
name := "proectj-name"version := "1.0"scalaVersion := "2.11.7"libraryDependencies ++= Seq( "org.scalatest" % "scalatest_2.11" % "3.0.0-SNAP5" % "test", "com.typesafe.play" % "play-json_2.11" % "2.4.2") |
И напишите тесты для оплаты:
|
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
|
import models._import models.Payment._import org.scalatest._import play.api.libs.json._class PaymentTest extends FlatSpec with Matchers { val address = Address("1375 Burlingame Ave.", None, "Burlingame", "California", "94010") "Payment " should "be converted to JSON correctly " in { val payment = Payment(1, "creditCard", address, "wdweadowei3209423", "123") val paymentJSON = writePayment(payment) (paymentJSON \ ("id")).get should be (JsNumber(1)) (paymentJSON \ ("type")).get should be (JsString("creditCard")) (paymentJSON \ ("address")).get should be (Json.toJson(payment.address)) (paymentJSON \ ("token")).get should be (JsString("wdweadowei3209423")) (paymentJSON \ ("cvv")).get should be (JsString("123")) } it should " be deserialized correctly " in { val paymentJSON: JsValue = JsObject(Seq( "id" -> JsNumber(1), "type" -> JsString("creditCard"), "address" -> Json.toJson(address), "token" -> JsString("wdweadowei3209423"), "cvv" -> JsString("123") )) val payment = readPayment(paymentJSON) payment.id should be (1) payment.pType should be ("creditCard") payment.address should be (address) payment.token should be ("wdweadowei3209423") payment.cvv should be ("123") }} |
Резюме
Модуль JSON Play действительно мощный. Я не описал много вещей, которые можно сделать с его помощью. Но я рекомендую вам прочитать официальную документацию и посмотреть другие примеры. Обратите особое внимание на версии документов, которые вы читаете, и Scala, которые вы используете в проекте.
| Ссылка: | Scala: работа с JSON от нашего партнера JCG Алексея Зволинского в блоге заметок Фрузенштейна . |