Skip to content

Instantly share code, notes, and snippets.

@fokot
Last active December 1, 2025 09:24
Show Gist options
  • Select an option

  • Save fokot/cde5e0a7409dc12c9de2fdfb2176703f to your computer and use it in GitHub Desktop.

Select an option

Save fokot/cde5e0a7409dc12c9de2fdfb2176703f to your computer and use it in GitHub Desktop.
Json with endpoints in zio-http
package com.simpleset
import zio.*
import zio.http.*
import zio.http.codec.*
import zio.http.codec.PathCodec.*
import zio.http.endpoint.*
import zio.http.endpoint.openapi.*
import zio.json.{DeriveJsonDecoder, DeriveJsonEncoder, JsonDecoder, JsonEncoder}
import zio.json.ast.Json
import zio.process.Command
import zio.schema.{DeriveSchema, Schema}
import zio.schema.annotation.description
import zio.schema.codec.json._
case class TestClass(
name: String,
more: Json
)
object TestClass {
given Schema[TestClass] = DeriveSchema.gen[TestClass]
given JsonDecoder[TestClass] = DeriveJsonDecoder.gen[TestClass]
given JsonEncoder[TestClass] = DeriveJsonEncoder.gen[TestClass]
}
object Main extends ZIOAppDefault:
opaque type UnparsedJson = String
// GET /dashboards - List all dashboards
val jsonEndpoint =
Endpoint(RoutePattern.GET / "json")
.in[Json]
.out[Json]
// POST /dashboards - Create or update a dashboard
val jsonFieldEndpoint =
Endpoint(RoutePattern.GET / "json-field")
.in[TestClass]
.out[TestClass]
val jsonUnparsedEndpoint =
Endpoint(RoutePattern.GET / "json-unparsed")
.in[UnparsedJson]
.out[UnparsedJson]
val jsonRoute = jsonEndpoint.implementHandler(handler { (json: Json) => ZIO.succeed(json).debug("json") })
val jsonFieldRoute = jsonFieldEndpoint.implementHandler(handler { (tc: TestClass) => ZIO.succeed(tc).debug("json-field") })
val jsonUnparsedRoute = jsonUnparsedEndpoint.implementHandler(handler { (u: UnparsedJson) => ZIO.succeed(u).debug("json-unparsed") })
def testEndpoint(endpoint: String) =
Console.printLine("\n\n" + ("*" * 20)) *>
Console.printLine(
s"""Testing $endpoint
|curl -X 'GET' \\
| 'http://localhost:8080/$endpoint' \\
| -H 'accept: application/json' \\
| -H 'Content-Type: application/json' \\
| -d '{"name": "john", "more": { "size": "big", "age": 10 }}'
|""".stripMargin) *>
Command("curl", "-X", "GET", s"http://localhost:8080/$endpoint",
"-H", "accept: application/json",
"-H", "Content-Type: application/json",
"-d", """{"name": "john", "more": { "size": "big", "age": 10 }}""",
).run.flatMap(process =>
process.exitCode.map(_.code).debug("exitCode") *> process.stdout.string.debug("stdout")
)
def run: ZIO[ZIOAppArgs & Scope, Throwable, Unit] =
for
_ <- Console.printLine(s"Starting ZIO-HTTP server. Open http://localhost:8080/docs/openapi")
openAPI = OpenAPIGen.fromEndpoints(
title = "API",
version = "1.0.0",
jsonEndpoint,
jsonFieldEndpoint,
jsonUnparsedEndpoint,
)
swaggerRoutes = SwaggerUI.routes(path("docs") / "openapi", openAPI)
allRoutes = Routes(jsonRoute, jsonFieldRoute, jsonUnparsedRoute) ++ swaggerRoutes
process <- Server.serve(allRoutes).provide(Server.default).fork
_ <- ZIO.sleep(2.seconds)
_ <- ZIO.foreach(List("json", "json-field", "json-unparsed"))(testEndpoint)
_ <- process.interrupt
// _ <- process.join
yield ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment