packages feed

tagliatelle-0.9.0: README.md

# 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.