Last active
April 9, 2025 17:46
-
-
Save hohonuuli/ab532acad9606f5b31df2faccce404c6 to your computer and use it in GitHub Desktop.
Example of using Circe with java.net.http
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env -S scala | |
// Brian Schlining. 2024-12-22 | |
//> using dep "io.circe::circe-core:0.14.10" | |
//> using dep "io.circe::circe-generic:0.14.10" | |
//> using dep "io.circe::circe-parser:0.14.10" | |
import io.circe.Decoder | |
import io.circe.generic.semiauto.deriveDecoder | |
import io.circe.parser.decode | |
import java.net.URI | |
import java.net.http.{HttpClient, HttpRequest, HttpResponse} | |
import java.nio.charset.StandardCharsets | |
// --- JSON Decoding --- | |
// Circe uses case classes to represent JSON objects | |
final case class Names(items: List[String], limit: Int, offset: Int, total: Int) | |
// Circe can automatically derive a Decoder for a case class | |
given Decoder[Names] = deriveDecoder[Names] | |
// This is a custom BodyHandler that uses Circe to decode the response body. | |
// It can decode any type T for which there is an implicit Decoder[T] in scope. | |
class CirceBodyHandler[T: Decoder] extends HttpResponse.BodyHandler[Either[Throwable, T]]: | |
override def apply(responseInfo: HttpResponse.ResponseInfo): HttpResponse.BodySubscriber[Either[Throwable, T]] = | |
HttpResponse | |
.BodySubscribers | |
.mapping(HttpResponse.BodySubscribers.ofString(StandardCharsets.UTF_8), s => decode[T](s)) | |
// Factory method for creating a CirceBodyHandler. This isn't strictly necessary, | |
// but it follows the java.net.http.HttpResponse.BodyHandlers factory method styles | |
object CirceBodyHandler: | |
def of[T: Decoder]: CirceBodyHandler[T] = new CirceBodyHandler[T]() | |
// -- Using the CirceBodyHandler with HttpClient -- | |
val uri = URI.create("https://database.fathomnet.org/worms/names") | |
val client = HttpClient.newHttpClient(); | |
val request = HttpRequest | |
.newBuilder() | |
.uri(uri) | |
.header("Accept", "application/json") | |
.GET() | |
.build() | |
val response = client.send(request, CirceBodyHandler.of[Names]) | |
response.body() match | |
case Left(e) => println(s"Failed to parse response: $e") | |
case Right(names) => println(s"Names: $names") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment