2017-03-14 129 views
2

我想玩elmplayground的源代码,我试图为博客创建配置json文件。我现在遇到的问题是,我不知道如何才能将帖子/页面作者解码为嵌套结构。我想要的是帖子和页面中的author字段对config.json中的作者进行引用。解码嵌套的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 alias Content = 
    { title : String 
    , name : String 
    , slug : String 
    , publishedDate : Date 
    , author : Author 
    , markdown : WebData String 
    , contentType : ContentType 
    , intro : String 
    } 

类型作者:

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

目前,这是我的配置解码器:

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) 

回答

3

我会先解码作者,然后用andThen将作者Dict转换为decodeContent。然后,您可以使用Decode.map将作者姓名转换为authorsDict中的查找。

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))) 
     -- … 

这会改变你的模型使用Maybe Author,但你也可以使用Decode.andThen并返回Decode.fail如果Dict.get回报Nothing

+0

我要试一试,但它看起来像我一直在寻找 – gabrielperales