2014-02-16 4 views
2

Итак, я недавно начал изучать Scala. Извините за мою некомпетентность заранее.Сериализация объектов Json Scala в структуре Play2.2.1

Я попытался найти ответ на stackoverflow. Мне удалось найти несколько связанных тем, но я не заметил своей проблемы.

Я пытаюсь отправить ответ json на основе объекта Scala. У меня есть Action, и я делаю следующее:

def oneCredential = Action { 
    val cred = Credential("John", "Temp", "5437437") 
    Ok(Json.toJson(cred)) 
} 

Я создал класс дела и соответствующие неявные Записывает [T] Из-за этого

import play.api.libs.json._ 
import play.api.libs.functional.syntax._ 
import play.api.libs.json.util._ 

case class Credential(name: String, account: String, password: String) 

object Credential{ 
    implicit val credentialWrites = (
    (__ \ "name").write[String] and 
    (__ \ "account").write[String] and 
    (__ \ "password").write[String] 
)(Credential) 
} 

Когда я пытаюсь запустить эту , У меня есть следующая ошибка: «Перегруженное значение метода [apply] не может применяться к (models.Credential.type)». Кроме того, я пробовал это

implicit val credentialWrites = (
     (__ \ "name").write[String] and 
     (__ \ "account").write[String] and 
     (__ \ "password").write[String] 
)(Credential.apply _) 

Ошибка. Ошибка: не удалось найти неявное значение для параметра фу: play.api.libs.functional.Functor [play.api.libs.json.OWrites]

Тогда это:

implicit val credentialWrites = (
    (__ \ "name").writes[String] and 
    (__ \ "account").writes[String] and 
    (__ \ "password").writes[String] 
)(Credential) 

Другой провал: " Значение write не является членом play.api.libs.json.JsPath. Примечание: неявное значение credentialWrites здесь не применимо, потому что оно появляется после точки приложения и в нем отсутствует явный тип результата ». Правильно, я понял первую часть ошибки, но не вторую.

Наконец я нашел стенограмму решение:

implicit val credentialWrites = Json.writes[Credential] 

С этим у меня нет никаких ошибок, и код, наконец, работал. Я нашел решение на этом blog. Говорят, что сокращенная форма точно такая же, как у «с надписью» выше. Но эта «длинная» форма не работала для меня.

Почему сокращенная версия работает, а длинная - нет? Может ли кто-нибудь объяснить это?

Спасибо!

PS Scala версия: 2.10.2

ответ

2

Определения вы данные будут работать на Reads, но Writes нужен другой вид аргумента в конце. Рассмотрим следующий пример:

case class Baz(foo: Int, bar: String) 

val r = (__ \ 'foo).read[Int] and (__ \ 'bar).read[String] 
val w = (__ \ 'foo).write[Int] and (__ \ 'bar).write[String] 

r может быть применен к функции (Int, String) => A получить Reads[A], что означает, что мы можем использовать его следующим образом (все эти эквивалент):

val bazReader1 = r((foo: Int, bar: String) => Baz(foo, bar)) 
val bazReader2 = r(Baz.apply _) 
val bazReader3 = r(Baz) 

То, что мы» повторное выполнение функции в аппликативный функтор для Reads, чтобы мы могли применить его к нашим Reads[Int] и Reads[String] (но вам не нужно заботиться об этом, если вы этого не хотите).

w принимает другой вид аргумента (опять же, вам не нужно заботиться, но это потому, что Writes имеет контравариантный функтор-он не имеет аппликативном функтор):

val bazWriter1 = w((b: Baz) => (b.foo, b.bar)) 

Мы мог бы написать это то же самое, как:

val bazWriter2 = w(unlift(Baz.unapply)) 

Здесь мы используем автоматически генерируемый экстрактор случае класса,, unapply, который возвращает Option[(Int, String)]. В этом случае мы знаем, что он всегда будет возвращать Some, поэтому мы можем использовать unlift (который исходит из пакета функционального синтаксиса и просто вызывает стандартную библиотеку Function.unlift), чтобы превратить Baz => Option[(Int, String)] в нужный Baz => (Int, String).

Так что просто измените свою окончательную строку на )(unlift(Credential.unapply)), и вы хорошо пойдете.

+0

спасибо. – Semuserable

Смежные вопросы