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.jsonis an InvariantEntity for Circe'sJSONtype, decoding and encoding Content-Typeapplication/json.Entity.htmlis an InvariantEntity forString, decoding and encoding Content-Typetext/html.Entity.scalatagsis an Entity decodingStringand encoding Scalatag'sTypedTag[String]type, with Content-Typetext/html.Entity.textis an InvariantEntity forString, decoding Content-Typetext/*and encoding Content-Typetext/plain.Entity.twirlis an Entity decodingStringand encoding Twirl'sHtmltype, with Content-Typetext/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]