tagliatelle: Tagged encodings that are not spaghetti

[ bsd3, json, library, text, web ] [ Propose Tags ] [ Report a vulnerability ]

A simple codec library for producing Data.Aeson.Values and a Data.OpenApi.Schema, focused on simplicity and performance.


[Skip to Readme]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.9.0
Change log CHANGELOG.md
Dependencies aeson (>=2.2.5 && <2.3), base (>=4.18 && <5), bytestring (>=0.11.5 && <0.13), containers (>=0.6.7 && <1), deepseq (>=1.4.8 && <1.6), hedgehog (>=1.7 && <1.8), insert-ordered-containers (>=0.2.7 && <0.3), microlens (>=0.5 && <0.6), openapi3 (>=3.2.5 && <3.3), tasty (>=1.5.4 && <1.6), tasty-hedgehog (>=1.4 && <1.5), text (>=2.0.2 && <3), vector (>=0.13.2 && <0.14) [details]
Tested with ghc ==9.12.3, ghc ==9.10.3, ghc ==9.6.7
License BSD-3-Clause
Author Victor Miraldo <vcm.oss@fastmail.com>
Maintainer Victor Miraldo <vcm.oss@fastmail.com>
Uploaded by vcmiraldo at 2026-06-02T17:48:50Z
Category Text, Web, JSON
Home page https://codeberg.org/VictorCMiraldo/tagliatelle
Bug tracker https://codeberg.org/VictorCMiraldo/tagliatelle/issues
Distributions
Downloads 1 total (1 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs uploaded by user
Build status unknown [no reports yet]

Readme for tagliatelle-0.9.0

[back to package description]

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; but I wanted something that did less, so I could get a lighter footprint.

Example

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