Module

Data.Codec.Argonaut

#JsonCodec

type JsonCodec a = BasicCodec (Either JsonDecodeError) Json a

Codec type for Json values.

#printJsonDecodeError

printJsonDecodeError :: JsonDecodeError -> String

Prints a JsonDecodeError as a somewhat readable error message.

#json

json :: JsonCodec Json

The "identity codec" for Json values.

#null

null :: JsonCodec Unit

A codec for null values in Json.

#boolean

boolean :: JsonCodec Boolean

A codec for Boolean values in Json.

#number

number :: JsonCodec Number

A codec for Number values in Json.

#int

int :: JsonCodec Int

A codec for Int values in Json.

#string

string :: JsonCodec String

A codec for String values in Json.

#codePoint

codePoint :: JsonCodec CodePoint

A codec for Codepoint values in Json.

#char

char :: JsonCodec Char

A codec for Char values in Json.

#jarray

jarray :: JsonCodec (Array Json)

A codec for Array Json values in Json. This does not decode the values of the array, for that use array for a general array decoder, or indexedArray with index to decode fixed length array encodings.

#jobject

jobject :: JsonCodec (Object Json)

A codec for JObject values in Json.

#void

void :: JsonCodec Void

A codec for Void values.

#array

array :: forall a. JsonCodec a -> JsonCodec (Array a)

A codec for arbitrary length Arrays where every item in the array shares the same type.

import Data.Codec.Argonaut as CA

codecIntArray ∷ CA.JsonCodec (Array Int)
codecIntArray = CA.array CA.int

#JIndexedCodec

type JIndexedCodec a = Codec (Either JsonDecodeError) (Array Json) (List Json) a a

Codec type for specifically indexed JArray elements.

#indexedArray

indexedArray :: forall a. String -> JIndexedCodec a -> JsonCodec a

A codec for types that are encoded as an array with a specific layout.

For example, if we'd like to encode a Person as a 2-element array, like ["Rashida", 37], we could write the following codec:

import Data.Codec ((~))
import Data.Codec.Argonaut as CA

type Person = { name ∷ String, age ∷ Int }

codecPerson ∷ CA.JsonCodec Person
codecPerson = CA.indexedArray "Test Object" $
  { name: _, age: _ }
    <$> _.name ~ CA.index 0 CA.string
    <*> _.age ~ CA.index 1 CA.int

#index

index :: forall a. Int -> JsonCodec a -> JIndexedCodec a

A codec for an item in an indexedArray.

#JPropCodec

type JPropCodec a = Codec (Either JsonDecodeError) (Object Json) (List (Tuple String Json)) a a

Codec type for JObject prop/value pairs.

#object

object :: forall a. String -> JPropCodec a -> JsonCodec a

A codec for objects that are encoded with specific properties.

See also Data.Codec.Argonaut.Record.object for a more commonly useful version of this function.

#prop

prop :: forall a. String -> JsonCodec a -> JPropCodec a

A codec for a property of an object.

#record

record :: JPropCodec (Record ())

The starting value for a object-record codec. Used with recordProp it provides a convenient method for defining codecs for record types that encode into JSON objects of the same shape.

For example, to encode a record as the JSON object { "name": "Karl", "age": 25 } we would define a codec like this:

import Data.Codec.Argonaut as CA
import Type.Proxy (Proxy(..))

type Person = { name ∷ String, age ∷ Int }

codecPerson ∷ CA.JsonCodec Person
codecPerson =
  CA.object "Person" $ CA.record
    # CA.recordProp (Proxy :: _ "name") CA.string
    # CA.recordProp (Proxy :: _ "age") CA.int

See also Data.Codec.Argonaut.Record.object for a more commonly useful version of this function.

#recordProp

recordProp :: forall proxy p a r r'. IsSymbol p => Cons p a r r' => proxy p -> JsonCodec a -> JPropCodec (Record r) -> JPropCodec (Record r')

Used with record to define codecs for record types that encode into JSON objects of the same shape. See the comment on record for an example.

#fix

fix :: forall a. (JsonCodec a -> JsonCodec a) -> JsonCodec a

Helper function for defining recursive codecs in situations where the codec definition causes a "The value of <codec> is undefined here" error.

import Data.Codec.Argonaut as CA
import Data.Codec.Argonaut.Common as CAC
import Data.Codec.Argonaut.Record as CAR
import Data.Maybe (Maybe)
import Data.Newtype (class Newtype)
import Data.Profunctor (wrapIso)

newtype IntList = IntList { cell ∷ Int, rest ∷ Maybe IntList }

derive instance newtypeLoopyList ∷ Newtype IntList _

codecIntList ∷ CA.JsonCodec IntList
codecIntList =
  CA.fix \codec →
    wrapIso IntList $
      CAR.object "IntList" { cell: CA.int, rest: CAC.maybe codec }

#prismaticCodec

prismaticCodec :: forall a b. String -> (a -> Maybe b) -> (b -> a) -> JsonCodec a -> JsonCodec b

Adapts an existing codec with a pair of functions to allow a value to be further refined. If the inner decoder fails an UnexpectedValue error will be raised for JSON input.

This function is named as such as the pair of functions it accepts correspond with the preview and view functions of a Prism-style lens.

An example of this would be a codec for Data.String.NonEmpty.NonEmptyString:

nonEmptyString ∷ CA.JsonCodec NES.NonEmptyString
nonEmptyString = CA.prismaticCodec "NonEmptyString" NES.fromString NES.toString CA.string

Another example might be to handle a mapping from a small sum type to strings:

data Direction = North | South | West | East

directionCodec :: JsonCodec Direction
directionCodec = CA.prismaticCodec "Direction" dec enc string
  where
    dec = case _ of
      "N" -> Just North
      "S" -> Just South
      "W" -> Just West
      "E" -> Just East
      _ -> Nothing

    enc = case _ of
      North -> "N"
      South -> "S"
      West -> "W"
      East -> "E"

Although for this latter case there are some other options too, in the form of Data.Codec.Argonaut.Generic.nullarySum and Data.Codec.Argonaut.Sum.enumSum.

Re-exports from Data.Codec

#encode

encode :: forall m a b c d. Codec m a b c d -> c -> b

#decode

decode :: forall m a b c d. Codec m a b c d -> a -> m d

#(~)

Operator alias for Data.Profunctor.lcmap (left-associative / precedence 5)

GCodec is defined as a Profunctor so that lcmap can be used to target specific fields when defining a codec for a product type. This operator is a convenience for that:

tupleCodec =
  Tuple
    <$> fst ~ fstCodec
    <*> snd ~ sndCodec

#(>~>)

Operator alias for Data.Codec.composeCodecFlipped (right-associative / precedence 8)

#(<~<)

Operator alias for Data.Codec.composeCodec (right-associative / precedence 8)

Modules