Entities

In HTTP, the term "entity" refers to the body of a request. For example, a JSON request will have JSON data in the entity. An Entity in Krop is responsible for converting an HTTP entity into a Scala type, and converting a Scala type into an HTTP entity. Entity is therefore a type of codec.

As well an decoding and encoding data, an Entity also specifies the Content-Type is supports for decoding and encoding. It is usually the case that the decoding Content-Type is more permissive than the encoding Content-Type. For example Entity.text will decode text/* but encodes text/plain.

The Entity type is defined as Entity[D, E], where D is the type of value that will be decoded from an HTTP request, and E is the type of values that will be encoded in a response. Most of the time D and E are the same, and the entity is called an InvariantEntity. Occassionally, however, they differ. For example, the ScalaTags entity decodes a String but encodes ScalaTags' data structure. This is because there is no parser from String to ScalaTags, so there is no way to parse an HTTP request with an HTML entity into ScalaTags.

Simple Entities

Simple entities decode and encode Scala types without an intermediaries. You should check the Entity companion object for the full list of supported entities, but here are some of the most commonly used:

  • Entity.json is an InvariantEntity for Circe's JSON type, decoding and encoding Content-Type application/json.
  • Entity.html is an InvariantEntity for String, decoding and encoding Content-Type text/html.
  • Entity.scalatags is an Entity decoding String and encoding Scalatag's TypedTag[String] type, with Content-Type text/html.
  • Entity.text is an InvariantEntity for String, decoding Content-Type text/* and encoding Content-Type text/plain.
  • Entity.twirl is an Entity decoding String and encoding Twirl's Html type, with Content-Type text/html.

JSON

Krop, by default, uses Circe for JSON decoding and encoding. If you have a type A that you want to decode and encode as JSON, assuming you have created given instances of Circe's Decoder and Encoder type for A, creating an InvariantEntity is as simple as calling Entity.jsonOf[A].

Here's a quick example, using Circe's semi-automatic generic derivation to create the Decoder and Encoder types.

import io.circe.{Decoder, Encoder}
import krop.all.*

final case class Cat(name: String) derives Decoder, Encoder

val jsonEntity = Entity.jsonOf[Cat]

Forms

Decoding and encoding of form data delegates to a FormCodec given instance. The usual way to create such an instance if with generic derivation. Here is an example, showing both generic derivation of the FormCodec instance and creation of an Entity using Entity.formOf.

final case class Dog(name: String) derives FormCodec

val formEntity = Entity.formOf[Dog]
Copyright © Noel Welsh. Built with 💖