2016-06-23 8 views
4

КонтекстСкала PlayJson Циклическая ссылка

У меня есть случай класс, который является элемент в иерархии, которая относится к себе как так:

case class Node(
    name:  String, 
    children: Option[Seq[Node]] = None 
) 

Я хотел бы PlayJson Format для этого.

Как правило, вы можете просто сделать:

implicit lazy val formatter = Json.format[MyCaseClass] 

Но это не работает.

Почему?

PlayJson использует макрос Scala для создания Format для класса случае, она будет проходить через все поля, когда он попадет в поле children он будет искать существующий форматировщик для Node, которые оно еще не построенным, заканчиваясь с ошибкой компиляции:

No implicit format for Option[Seq[Node]] available. 
[error] implicit lazy val formatter = Json.format[Node] 

Вопросы

Какой самый лучший способ приблизиться к этому?
Это известная проблема с макросом формата PlayJson?

ответ

5

Это то, что можно найти в recursive types в плей-JSON docs:

import play.api.libs.functional.syntax._ 
import play.api.libs.json.{Reads, Writes, _} 

case class Node(name: String, children: Option[Seq[Node]] = None) 

implicit lazy val nodeReads: Reads[Node] = (
    (__ \ "name").read[String] and 
    (__ \ "children").lazyReadNullable(Reads.seq[Node](nodeReads)) 
)(Node) 

implicit lazy val nodeWrites: Writes[Node] = (
    (__ \ "name").write[String] and 
    (__ \ "children").lazyWriteNullable(Writes.seq[Node](nodeWrites)) 
)(unlift(Node.unapply)) 

Так как в этом случае Reads и Writes симметричны, вы можете создать все это как единый Format:

implicit lazy val nodeFormat: Format[Node] = (
    (__ \ "name").format[String] and 
    (__ \ "children").lazyFormatNullable(Reads.seq[Node](nodeFormat), Writes.seq[Node](nodeFormat)) 
)(Node.apply, unlift(Node.unapply)) 
+0

Блестящий, спасибо за указатель! –

+1

Проверьте мое редактирование, все это можно немного сократить. –

+0

Кажется, что-то, что должно быть усвоено для макроса. Я еще не играл с моим собственным макросом в Scala; есть ли что-то конкретное в отношении макросов Scala, что означает, что это невозможно? –

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