Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support hierarchies with cyclical dependencies #9

Open
manuelbernhardt opened this issue Mar 2, 2015 · 1 comment
Open

Support hierarchies with cyclical dependencies #9

manuelbernhardt opened this issue Mar 2, 2015 · 1 comment

Comments

@manuelbernhardt
Copy link
Contributor

sealed trait Parent
case class A(b: B) extends Parent
case class B(foo: String) extends Parent

This may go wrong depending on which (random? alphabetical?) order the subclasses are detected because the macro then generates code containing a forward reference. I'm not sure how easy this is to fix. I know the Play JSON macro has a mechanism for warning of such cases (i.e. it fails if it can't find an implicit JSON format in scope), one idea would be to take into account the order of declaration of the subclasses in code by doing a tree traversal and sort the subclasses discovered at compile-time according to that order (but I don't know how easy that is, I have only a limited experience with macros). Or another approach could be to do a topological sort on the subclasses should they reference symbols that are also subclasses of the trait.

@OlegIlyenko
Copy link
Contributor

In general you can implement this example like this:

sealed trait Parent
case class A(b: B) extends Parent
case class B(foo: String) extends Parent

object Parent {
  implicit val bJson: JSON[B] = deriveJSON[B]
  implicit val parentJson: JSON[Parent] = deriveJSON[Parent]
}

println(toJSON(A(B("hello")): Parent))

it will print:

{"b":{"foo":"hello"},"type":"A"}

It works, because ToJSON/FromJSON and JSON type classes are invariant and deriveJSON[Parent] generates serializer only for type Parent. This also mean, that deriveJSON[Parent] will not work for toJSON(A(...)) or toJSON(B(...)). That's why you also need another serializer for B.

That said both of these scenarios:

sealed trait Parent
case class A(b: Option[B]) extends Parent
case class B(a: Option[A]) extends Parent

and

sealed trait Parent
case class A(b: Parent) extends Parent
case class B(A: String) extends Parent

are not supported at the moment. Do you think that one/both of these scenarios are also in the scope of this issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants