aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/main.scala
blob: 223ac1cda20fd5050c0c8a7957b20305cabadd82 (plain) (blame)
1
2
3
4
5
6
7
8
9
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import spray.json._

// product type
case class Foo(x: Int)
case class Bar(foo: Foo, str: String)

// coproduct
sealed trait T
case object A extends T
case class B(a: String) extends T
case class C(x: T) extends T // inception!

object Main extends App with DefaultJsonProtocol with DerivedFormats {

  println("//////////\nProducts:")

  {
    val product = Bar(Foo(42), "hello world")
    val js = product.toJson
    println(js.prettyPrint)
    println(js.convertTo[Bar])
  }

  println("//////////\nCoproducts:")

  {
    val coproduct: T = B("hello wordld") //Seq(C(B("What's up?")), B("a"), A)
    val js = coproduct.toJson
    println(js.prettyPrint)
    println(js.convertTo[T])
  }

}

/*
A potentital danger:

Overriding generated formats is possible (see CustomFormats), however it can be
easy to forget to include the custom formats.
=> In that case, the program will still compile, however it won't use the
   correct format!

Possible workarounds?

  - Require explicit format declarations, i.e. remove implicit from `implicit def
    gen[T] = macro Magnolia.gen[T]` and add `def myFormat = gen[Foo]` to every
    format trait.
    => requires manual code, thereby mostly defeats the advantages of automatic derivation
    => (advantage, no more code duplication since macro is expanded only once)

  - Avoid custom formats.
    => entities become "API objects", which will be hard to upgrade in a backwards-compatible, yet idiomatic way
       (E.g. new fields could be made optional so that they won't be required in json, however the business logic
       may not require them to be optional. We lose some typesafety.)
       => we'd likely have an additional layer of indirection, that will convert "api objects" to "business objects"
          implemented by services
          => Is that a good or bad thing?
*/