Skip to content

Instantly share code, notes, and snippets.

@loicdescotte
Last active January 19, 2024 09:00
Show Gist options
  • Save loicdescotte/8ab10c13b7c63920ec5637b5c695368b to your computer and use it in GitHub Desktop.
Save loicdescotte/8ab10c13b7c63920ec5637b5c695368b to your computer and use it in GitHub Desktop.
Process web services and transform data with type classes #ZIO #Generic #Scala
object TestApp extends App :
import zio.json._
case class Input[A](hits: List[A])
trait Transformer[A,B] :
extension(a: A) def transform: B
object Input :
implicit def decoder[A: JsonDecoder]: JsonDecoder[Input[A]] = DeriveJsonDecoder.gen[Input[A]]
def read[A: JsonDecoder](readUrl: String): Option[Input[A]] =
import Input._
// simulate ws call :
val response = """
|{
|"hits" : [
| { "name": "a", "value": 0 },
| { "name": "b", "value": 1 }
| ]
|}
|""".stripMargin
response.fromJson[Input[A]].left.map(e => println(e)).toOption
def write[A](transformed: List[A]) =
transformed.foreach(x => println(s"writing $x"))
def process[A, B](readUrl: String)(using JsonDecoder[A], Transformer[A, B]): Unit =
val input: Option[Input[A]] = read(readUrl)
// transform is accessible via Transformer typeclass
val transformed = input.map(_.hits.map(_.transform))
transformed.foreach(write)
case class DummyIn(name: String, value: Int)
case class DummyOut(name: String, value: Int)
given JsonDecoder[DummyIn] = DeriveJsonDecoder.gen[DummyIn]
given Transformer[DummyIn, DummyOut] with
extension (dummyIn: DummyIn) def transform: DummyOut = DummyOut(dummyIn.name.toUpperCase, dummyIn.value)
process[DummyIn, DummyOut]("http://my-service")
@loicdescotte
Copy link
Author

Result :

writing DummyOut(A,0)
writing DummyOut(B,1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment