# Tagliatelle
Simple codec-style library for `ToJSON`, `FromJSON` and `ToSchema`. Main design goals are:
1. Fast and Lean: tagliatelle codecs are cheap to compile and cheap to run. The performance is comparable to
hand-written `ToJSON/FromJSON` instances, even beating it for some types.
2. Explicit: You control the representation, no automatic anything. This makes it eaiser to keep the API backwards compatible
while the code itself evolves as needed.
3. Easy to use: Tries to minimise the boilerplate you need to maintain your codecs.
4. Domain Specific: it's meant for helping maintaining Haskell services with a large HTTP API; there won't be other formats. The librrary has been designed to make it easy to write codecs for Haskell datatypes in the sum-of-products with record accessors, because that's how I write most of my types.
This library was inspired by [`autodocodec`](https://github.com/NorfairKing/autodocodec); but I wanted something
that did less, so I could get a lighter footprint.
## Example
```haskell
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE LambdaCase #-}
data TaskBody =
Unstructured {body :: Text}
| Absent
| SubtasksMap { subtasksMap :: Map.Map TaskId TaskBody }
| SubtasksList { subtasksList :: [TaskBody] }
deriving (Eq, Show)
newtype TaskId = TaskId { taskId :: Int32 }
deriving newtype (Eq, Show, Ord, IsKey, HasCodec)
instance HasCodec TaskBody where
codec = coprod @"type" "TaskBody"
(\case
Unstructured {} -> unstructuredFields
Absent {} -> absentFields
SubtasksList {} -> subtasksListFields
SubtasksMap {} -> subtasksMapFields
)
[unstructuredFields, absentFields, subtasksListFields, subtasksMapFields]
where
unstructuredFields = Tagged "unstructured" $ Unstructured <$> field "body" body codec
absentFields = Tagged "absent" $ pure Absent
subtasksListFields = Tagged "subtasks_list" $ SubtasksList <$> field "subtasks" subtasksList codec
subtasksMapFields = Tagged "subtasks_map" $ SubtasksMap <$> field "subtasks" subtasksMap codec
```
This codec will produce JSON that, once formatted, looks like:
```
{
"type": "subtasks_map",
"subtasks": {
"42": {
"type": "subtasks_list",
"subtasks": [
{
"type": "unstructured",
"body": "test 1"
},
{
"type": "absent"
},
{
"type": "unstructured",
"body": "test 2"
}
]
}
}
}
```
Note that each hardcoded `Text` only shows up once: this makes it impossible to have spelling errors on tags between
encoder and decoder.