FabienHenon / jsonapi / JsonApi.Resource

JsonApi.Resource exposes the Resource type and functions to get and set information for your resources.

Type


type alias Resource =
JsonApi.Internal.ResourceInfo.ResourceInfo

The Resource represents a resource. It is passed to your resource decoders, but you can also use it to encode resources to json api, via a Document. It contains useful information for decoding and encoding your resource: resource id, links, attributes, relationships, ...

_Example of json api

{
    "data": [
        {
            "type": "users",
            "id": "13608770-76dd-47e5-a1c4-4d0d9c2483ad",
            "links": {
                "self": "http://link-to-user",
                "profile": "http://link-to-user-profile"
            },
            "attributes": {
                "firstname": "John",
                "lastname": "Doe",
                "gender": "male"
            },
            "relationships": {}
        }
    ]
}

And how to build it with the JsonApi.Resource module:

build "users"
    |> withId "13608770-76dd-47e5-a1c4-4d0d9c2483ad"
    |> withLinks
        (Dict.fromList
            [ ( "self", "http://link-to-user" )
            , ( "profile", "http://link-to-user-profile" )
            ]
        )
    |> withAttributes
        [ ( "firstname", string "John" )
        , ( "lastname", string "Doe" )
        , ( "gender", string "male" )
        ]


type alias OneOrManyRelationships =
JsonApi.Internal.ResourceInfo.OneOrManyRelationships

This type is used to represent either one or many relationships in your Resource object.

See withRelationship function for more information


type OneOrMoreRelationshipData
    = NoRelationship
    | One RelationshipData
    | Many (List RelationshipData)

Relationship's data object. It's a variant type because in a relationship the data field can either: be null, have one relationship, have many relationships.

See getRelationshipsDesc for more information


type alias RelationshipData =
{ id : String
, type_ : String 
}

Description of the data object in a relationship object. Contains the id of the relationship and it's type

See getRelationshipsDesc for more information


type alias RelationshipDesc =
{ data : OneOrMoreRelationshipData
, links : Dict String String 
}

The description of a relationship in the relationships field of the jsonapi object.

For instance (in jsonapi):

"relationships": {
    "creator": {
        "data": {
            "type": "creators",
            "id": "22208770-76dd-47e5-a1c4-4d0d9c2483ad"
        },
        "links": {
            "related": "http://link-to-creator/1"
        }
    }
}

This type contains the links defined in the relationship and the data object of the relationship

See getRelationshipsDesc for more information

New resource

build : String -> Resource

Builds a new Resource with the specified type name

You can build your resources like this:

myResource : Post -> Resource
myResource post =
    build "posts"
        |> withId "post-1"
        |> withLinks (Dict.fromList [ ( "self", "http://url-to-post/1" ) ])

fromResource : String -> Resource -> Resource

Builds a new Resource from the specified Resource and with the specified type name

You can build your resources like this:

myResource : Resource -> Resource
myResource resource =
    fromResource "posts" resource

Getter functions

id : Resource -> String

Returns the id of your resource.

From the json example above, id will return 13608770-76dd-47e5-a1c4-4d0d9c2483ad

links : Resource -> Dict String String

Returns the links of your resource.

From the json example above, links will return a Dict with this value:

[ ( "self", "http://link-to-user" )
, ( "profile", "http://link-to-user-profile" )
]

resType : Resource -> String

Returns the type of your resource.

From the json example above, type_ will return users

getRelationshipsDesc : Resource -> Dict String RelationshipDesc

Returns the relationships description of your resource.

This is not a way to decode a relationship, only a quick way to get the relationship ids and types

type alias Post =
    { id : String
    , links : Dict String String
    , title : String
    , content : String
    , relationships : Dict String JsonApi.Resource.RelationshipDesc
    }

decoder : Resource -> Decoder Post
decoder resourceInfo =
    map5 Post
        (succeed (JsonApi.Resource.id resourceInfo))
        (succeed (JsonApi.Resource.links resourceInfo))
        (field "title" string)
        (field "content" string)
        (succeed (JsonApi.Resource.getRelationshipsDesc resourceInfo))

Say the relationships for this post are:

"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"
            }
        ]
    }
}

Then you will get these information:

Dict.get "creator" post.relationships

Just
    { links = [ ( "related", "http://link-to-creator/1" ) ]
    , data =
        JsonApi.Resource.One
            { id = "22208770-76dd-47e5-a1c4-4d0d9c2483ad"
            , type_ = "creators"
            }
    }

Dict.get "comments" post.relationships

Just
    { links = []
    , data =
        JsonApi.Resource.Many
            [ { id = "22208770-76dd-47e5-a1c4-4d0d9c2483ab"
              , type_ = "comment"
              }
            , { id = "cb0759b0-03ab-4291-b067-84a9017fea6f"
              , type_ = "comment"
              }
            ]
    }

Setter functions

withId : String -> Resource -> Resource

Sets the id of the Resource object

myResource : Post -> Resource
myResource post =
    build "posts"
        |> withId "post-1"

withLinks : Dict String String -> Resource -> Resource

Sets the links of the Resource object

myResource : Post -> Resource
myResource post =
    build "posts"
        |> withLinks (Dict.fromList [ ( "self", "http://url-to-post/1" ) ])

withAttributes : List ( String, Json.Encode.Value ) -> Resource -> Resource

Sets the attributes of the Resource object. This is the payload of your resource.

myResource : Post -> Resource
myResource post =
    build "posts"
        |> withAttributes
            [ ( "firstname", string "John" )
            , ( "lastname", string "Doe" )
            , ( "gender", string "male" )
            ]

withRelationship : String -> OneOrManyRelationships -> Resource -> Resource

Adds a relationship in the Resource object. You have to pass it the name of the relationship and a description of the relationship resource (See relationship and relationships)

myResource : Post -> Resource
myResource post =
    build "posts"
        |> withRelationship "creators" (relationship creator.id (creatorResource creator))

Relationships

relationship : String -> Resource -> OneOrManyRelationships

Defines a relationship that can then be added to its parent Resource. It takes the id of the resource and the resource.

creatorResource : Creator -> Resource
creatorResource creator =
    build "creator"
        |> withAttributes [ ( "firstname", string creator.firstname ) ]

myResource : Post -> Resource
myResource post =
    build "posts"
        |> withRelationship "creators" (relationship creator.id (creatorResource creator))

relationships : List ( String, Resource ) -> OneOrManyRelationships

Defines a list of relationships that can then be added to a parent Resource. It takes a List of Tuples with the id of the resource and the resource.

commentResource : Comment -> Resource
commentResource comment =
    build "comment"
        |> withAttributes [ ( "content", string comment.content ) ]

myResource : Post -> Resource
myResource post =
    build "posts"
        |> withRelationship "comments" (relationships (List.map (\comment -> ( "comment", commentResource comment )) comments))