FabienHenon / jsonapi / JsonApi.Decode

Provides functions to decode json api document with their resources and their relationships

Example json:

```json { "meta": { "redirect": true }, "data": [ { "type": "posts", "id": "13608770-76dd-47e5-a1c4-4d0d9c2483ad", "links": { "self": "http://link-to-post/2" }, "attributes": { "title": "First post", "content": "First post content" }, "relationships": { "creator": { "data": { "type": "creators", "id": "22208770-76dd-47e5-a1c4-4d0d9c2483ad" }, "links": { "related": "http://link-to-creator/1" } }, "comments": { "links": {}, "data": [ { "type": "comment", "id": "22208770-76dd-47e5-a1c4-4d0d9c2483ab" }, { "type": "comment", "id": "cb0759b0-03ab-4291-b067-84a9017fea6f" } ] } } }, { "type": "posts", "id": "13608770-76dd-47e5-a1c4-4d0d9c2483ae", "links": { "self": "http://link-to-post/2" }, "attributes": { "title": "Second post", "content": "Second post content" }, "relationships": { "creator": { "data": { "type": "creators", "id": "22208770-76dd-47e5-a1c4-4d0d9c2483ad" }, "links": { "related": "http://lnk-to-creator/1" } }, "comments": { "links": {}, "data": [ { "type": "comment", "id": "22208770-76dd-47e5-a1c4-4d0d9c2483ac" } ] } } } ], "included": [ { "type": "creators", "id": "22208770-76dd-47e5-a1c4-4d0d9c2483ad", "attributes": { "firstname": "John", "lastname": "Doe" }, "links": { "self": "http://link-to-creator/1" }, "relationships": {} }, { "type": "comment", "id": "22208770-76dd-47e5-a1c4-4d0d9c2483ac", "attributes": { "content": "Comment 1 content", "email": "john

Decoders

resources : String -> (JsonApi.Resource.Resource -> Json.Decode.Decoder a) -> Json.Decode.Decoder (Result (List Error) (JsonApi.Document.Document JsonApi.Document.NoMeta (List a)))

Decode a document and its resources from the json api content.

You pass it the type of the resources ("posts" in our example above) and the resource decoder and it will return a new Decoder representing a Document with NoMeta and a List of your resources, OR a list of Errors.

Here is an example of resource Decoder:

type alias Post =
    { id : String
    , title : String
    , content : String
    }

postDecoder : Resource -> Decoder Post
postDecoder resourceInfo =
    map3 Post
        (succeed (JsonApi.Resource.id resourceInfo))
        (field "title" string)
        (field "content" string)

-- Decoder for our posts from json api
resources "posts" postDecoder

resource : String -> (JsonApi.Resource.Resource -> Json.Decode.Decoder a) -> Json.Decode.Decoder (Result (List Error) (JsonApi.Document.Document JsonApi.Document.NoMeta a))

Decode a document with only one resource from the json api content.

You pass it the type of the resource ("posts" in our example above) and the resource decoder and it will return a new Decoder representing a Document with NoMeta and your resource, OR a list of Errors.

(The json data attribute is an object and not a list)

Here is an example of resource Decoder:

type alias Post =
    { id : String
    , title : String
    , content : String
    }

postDecoder : Resource -> Decoder Post
postDecoder resourceInfo =
    map3 Post
        (succeed (JsonApi.Resource.id resourceInfo))
        (field "title" string)
        (field "content" string)

-- Decoder for our post from json api
resource "posts" postDecoder

resourcesWithMeta : String -> (JsonApi.Resource.Resource -> Json.Decode.Decoder a) -> Json.Decode.Decoder meta -> Json.Decode.Decoder (Result (List Error) (JsonApi.Document.Document meta (List a)))

Decode a document, its meta object and its resources from the json api content.

You pass it the type of the resources ("posts" in our example above), the resource decoder and the meta decoder and it will return a new Decoder representing a Document with your meta object and a List of your resources, OR a list of Errors.

Here is an example of resource Decoder with meta:

type alias Post =
    { id : String
    , title : String
    , content : String
    }

type alias Meta =
    { redirect : Bool
    }

postDecoder : Resource -> Decoder Post
postDecoder resourceInfo =
    map3 Post
        (succeed (JsonApi.Resource.id resourceInfo))
        (field "title" string)
        (field "content" string)

metaDecoder : Decoder Meta
metaDecoder =
    map Meta
        (field "redirect" bool)

-- Decoder for our posts from json api
resourcesWithMeta "posts" postDecoder metaDecoder

resourceWithMeta : String -> (JsonApi.Resource.Resource -> Json.Decode.Decoder a) -> Json.Decode.Decoder meta -> Json.Decode.Decoder (Result (List Error) (JsonApi.Document.Document meta a))

Decode a document, its meta object and only one resource from the json api content.

You pass it the type of the resources ("posts" in our example above), the resource decoder and the meta decoder and it will return a new Decoder representing a Document with your meta object and your resource, OR a list of Errors.

(The json data attribute is an object and not a list)

Here is an example of resource Decoder with meta:

type alias Post =
    { id : String
    , title : String
    , content : String
    }

type alias Meta =
    { redirect : Bool
    }

postDecoder : Resource -> Decoder Post
postDecoder resourceInfo =
    map3 Post
        (succeed (JsonApi.Resource.id resourceInfo))
        (field "title" string)
        (field "content" string)

metaDecoder : Decoder Meta
metaDecoder =
    map Meta
        (field "redirect" bool)

-- Decoder for our post from json api
resourceWithMeta "posts" postDecoder metaDecoder

relationship : String -> JsonApi.Resource.Resource -> (JsonApi.Resource.Resource -> Json.Decode.Decoder a) -> Json.Decode.Decoder a

Decode a relationship from your json api resources.

You pass it the type of the relationship resource ("creator" in our example above), the ResourceInfo passed to your resources Decoder and the relationship decoder. It will return a new Decoder representing the relationship.

Here is an example of resource Decoder with a relationship:

type alias Post =
    { id : String
    , title : String
    , content : String
    , creator : Creator
    }

type alias Creator =
    { id : String
    , firstname : String
    , lastname : String
    }

creatorDecoder : Resource -> Decoder Creator
creatorDecoder resourceInfo =
    map3 Creator
        (succeed (JsonApi.Resource.id resourceInfo))
        (field "firstname" string)
        (field "lastname" string)

postDecoder : Resource -> Decoder Post
postDecoder resourceInfo =
    map4 Post
        (succeed (JsonApi.Resource.id resourceInfo))
        (field "title" string)
        (field "content" string)
        (relationship "creator" resourceInfo creatorDecoder)

-- Decoder for our posts and its creator from json api
resources "posts" postDecoder

relationships : String -> JsonApi.Resource.Resource -> (JsonApi.Resource.Resource -> Json.Decode.Decoder a) -> Json.Decode.Decoder (List a)

Decode a list of relationships from your json api resources.

You pass it the type of the relationship resource ("comments" in our example above), the ResourceInfo passed to your resources Decoder and the relationship decoder. It will return a new Decoder representing the List of relationships.

Here is an example of resource Decoder with a list of relationships:

type alias Post =
    { id : String
    , title : String
    , content : String
    , comments : List Comment
    }

type alias Comment =
    { id : String
    , content : String
    , email : String
    }

commentDecoder : Resource -> Decoder Comment
commentDecoder resourceInfo =
    map3 Comment
        (succeed (JsonApi.Resource.id resourceInfo))
        (field "content" string)
        (field "email" string)

postDecoder : Resource -> Decoder Post
postDecoder resourceInfo =
    map4 Post
        (succeed (JsonApi.Resource.id resourceInfo))
        (field "title" string)
        (field "content" string)
        (relationships "comments" resourceInfo commentDecoder)

-- Decoder for our posts and its creator from json api
resources "posts" postDecoder

meta : Json.Decode.Decoder meta -> Json.Decode.Decoder (Result (List Error) (JsonApi.Document.Document meta JsonApi.Document.NoData))

Decode a document, its meta object and no resource from the json api content.

You pass it the meta decoder and it will return a new Decoder representing a Document with your meta object and no resource, OR a list of Errors.

(No data property is decoded from the json api document)

Here is an example of document Decoder with only meta:

type alias Meta =
    { redirect : Bool
    }

metaDecoder : Decoder Meta
metaDecoder =
    map Meta
        (field "redirect" bool)

-- Decoder for our meta object from json api
meta metaDecoder

Errors


type alias Error =
{ id : Maybe String
, links : Maybe (Dict String String)
, status : Maybe String
, code : Maybe String
, title : Maybe String
, detail : Maybe String
, source : Maybe Json.Decode.Value
, meta : Maybe Json.Decode.Value 
}

Error object containing information about the error in the document

errorToFailure : Json.Decode.Decoder (Result (List Error) (JsonApi.Document.Document meta data)) -> Json.Decode.Decoder (JsonApi.Document.Document meta data)

Converts a Decoder with an Err Result to a failed Decoder, and a Decoder with an Ok Result to a succeed Decoder with the Document.