2

I'm trying playing with the source code of elmplayground and I'm trying to create a configuration json file for the blog. The issue I'm having at this point is that I don't know how I can decode a post/page author as a nested structure. What I want is that the author field in posts and pages do a reference to an author in the config.json.

config.json:

{
 "posts": [{
 "slug": "/hello-world",
 "title": "Hello World",
 "name": "hello-world",
 "publishedDate": "2016-10-30",
 "author": "Gabriel",
 "intro": ""
 }],
 "pages": [{
 "slug": "/hello",
 "name": "index",
 "title": "Elm Playground",
 "publishedDate": "2016-09-01",
 "author": "Gabriel",
 "intro": ""
 }],
 "authors": {
 "Gabriel": {
 "name": "Gabriel Perales",
 "avatar": "..."
 }
 }
}

Type Content for pages and posts:

type alias Content =
 { title : String
 , name : String
 , slug : String
 , publishedDate : Date
 , author : Author
 , markdown : WebData String
 , contentType : ContentType
 , intro : String
 }

Type Author:

type alias Author =
 { name : String
 , avatar : String
 }

Currently this is my config decoder:

configDecoder : Decoder Config
configDecoder =
 Decode.map2 Config
 (field "posts" <| Decode.list <| decodeContent Post)
 (field "pages" <| Decode.list <| decodeContent Page)
decodeContent : ContentType -> Decoder Content
decodeContent contentType =
 Decode.map8 Content
 (field "slug" string)
 (field "name" string)
 (field "title" string)
 (field "publishedDate" decodeDate)
 (field "author"
 (string
 -- I want to decode the author from "authors"
 -- I have tried with 
 -- (\name -> at ["authors", name] decodeCofigAuthor) but it doesn\'t work
 |> andThen (\name -> Decode.succeed <| Author name "...")
 )
 )
 (Decode.succeed RemoteData.NotAsked)
 (Decode.succeed contentType)
 (field "intro" string)
decodeConfigAuthor : Decoder Author
decodeConfigAuthor =
 Decode.map2 Author
 (field "name" string)
 (field "avatar" string)
asked Mar 14, 2017 at 14:03

1 Answer 1

3

I would start by decoding the authors, and then use andThen to pass the authors Dict into decodeContent. You can then use Decode.map to convert to author name into a lookup in the authors Dict.

decoder =
 (field "authors" <| Decode.dict <| authorDecoder)
 |> Decode.andThen configDecoder
configDecoder authors =
 Decode.map2 Config
 (field "posts" <| Decode.list <| decodeContent Post authors)
 (field "pages" <| Decode.list <| decodeContent Page authors)
decodeContent contentType authors =
 Decode.map8 Content
 -- ...
 (field "author" (string |> Decode.map (\name -> Dict.get name authors)))
 -- ...

This would change your model to use a Maybe Author, but you could also use Decode.andThen and return a Decode.fail if Dict.get returns Nothing.

gabrielperales
8,0731 gold badge23 silver badges20 bronze badges
answered Mar 14, 2017 at 14:55
Sign up to request clarification or add additional context in comments.

1 Comment

I'm going to try it, but it looks like what I was looking for

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.