2016-02-11 1 views
0

компиляции:Реализация неявных Записывает для результата запроса присоединиться ошибки

No Json serializer found for type Seq[(models.Account, models.Company)]. Try to implement an implicit Writes or Format for this type. 

Как я могу определить неявное пишет в результате присоединения запроса?

Контроллер:

def someEndpoint = Action.async { implicit request => 
    val query = for { 
     a <- accounts if a.id === 10 
     c <- companies if a.companyID === c.id 
    } yield (a, c) 
    db.run(query.result).map(rows => Ok(Json.toJson(rows))) // Causes compilation error 
} 

Каждый из моих моделей (счета и компании) имеют свои собственные неявные пишет (здесь компания одна):

case class Company(id: Int, name: String) 

object Company { 
    implicit val writes = new Writes[Company] { 
    def writes(company: Company): JsValue = { 
     Json.obj(
     "id" -> company.id, 
     "name" -> company.name 
    ) 
    } 
    } 
} 

Можно динамически обрабатывать сериализации для соединений? У меня есть много вещей, с которыми я буду объединять ... Нужно ли мне явно определять writes для каждой комбинации?

ответ

1

Writes.seq поможет вам

уменьшенного писателю

val w = (
    (__ \ "account").write[Account] and 
    (__ \ "company").write[Company] 
).tupled 

помогает вы можете превратить Seq[(models.Account, models.Company)] в JsValue с

Writes.seq(w).writes(rows) 

и последняя команда будет

db.run(query.result).map(rows => Ok(Writes.seq(w).writes(rows)) 

или более ясный вариант

db.run(query.result) 
    .map(
    _.map{ 
     case (a,c) => Json.obj("account" -> a, "company" -> c) 
    } 
) 
    .map(rows => 
    Ok(JsArray(rows)) 
) 

это то же самое, но вы создаете объект для каждый ряд.

0

Я думаю, что вы ожидаете ответа вашего запроса в формате JSON, чтобы быть чем-то вроде

[ 
    { 
    "account" : { "number": "123", "companyID" : 1 }, 
    "company" : { "id" : 1, "name" : "My company"} 
    } , ... 
] 

Проблема заключается в ответ на запрос только кортеж, так что «счет» и «компания» не так просто вычислять.

Вместо кортежа вы можете создать новый класс case со связанными данными, но я понимаю, что вы хотите этого избежать. В этом случае вместо кортежа вы можете использовать карту, которая автоматически преобразуется в JSON.

Extra: Создания писателей для конкретных классов очень просто

import play.api.libs.json._ 
implicit val personWrites = Json.writes[Person] 

Ссылка: https://www.playframework.com/documentation/2.4.x/ScalaJsonInception

+0

Как получить запрос для возврата карты вместо кортежа? – Tyler

+0

Вы можете сделать это в своем понимании урока Map («account» -> Json.toJson (a) »,« company »-> Json.toJson (c)) или сопоставить строки и создать карту только при создании ответа. –

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

  • Нет связанных вопросов^_^