在 Elm 中解析嵌套 JSON

Parsing nested JSON in Elm

我有这种情况

-- this is in post.elm
type alias Model =
  { img : String
  , text : String
  , source : String
  , date : String
  , comments : Comments.Model
  }

-- this is in comments.elm
type alias Model =
  List Comment.Model

-- this is in comment.elm
type alias Model =
  { text : String
  , date : String
  }

我正在尝试解析一个JSON这样形成的

{
  "posts": [{
    "img": "img 1",
    "text": "text 1",
    "source": "source 1",
    "date": "date 1",
    "comments": [{
      "text": "comment text 1 1",
      "date": "comment date 1 1"
    }]
  }
}

这是我的Decoder

decoder : Decoder Post.Model
decoder =
  Decode.object5
    Post.Model
    ("img" := Decode.string)
    ("text" := Decode.string)
    ("source" := Decode.string)
    ("date" := Decode.string)
    ("comments" := Decode.list Comments.Model)

decoderColl : Decoder Model
decoderColl =
  Decode.object1
    identity
    ("posts" := Decode.list decoder)

它不起作用,我得到

Comments does not expose Model.

如何公开 type alias

如何为我的示例设置 Decoder

编辑:更新至 Elm 0.18

要公开 Comments.Model,请确保您的 Comments.elm 文件公开所有类型和函数,如下所示:

module Comments exposing (..)

或者,您可以像这样公开类型和函数的子集:

module Comments exposing (Model)

您的解码器存在一些问题。首先,为了匹配您的 JSON,您将需要一个公开单个 posts 列表帖子的记录类型别名。

type alias PostListContainerModel =
  { posts : List Post.Model }

您缺少评论解码器。看起来像这样:

commentDecoder : Decoder Comment.Model
commentDecoder =
  Decode.map2
    Comment.Model
    (Decode.field "text" Decode.string)
    (Decode.field "date" Decode.string)

我要把你的 decoder 函数重命名为 postDecoder 以避免歧义。现在您可以使用新的 commentDecoder.

修复 comments 解码器行
postDecoder : Decoder Post.Model
postDecoder =
  Decode.map5
    Post.Model
    (Decode.field "img" Decode.string)
    (Decode.field "text" Decode.string)
    (Decode.field "source" Decode.string)
    (Decode.field "date" Decode.string)
    (Decode.field "comments" (Decode.list commentDecoder))

最后,我们可以使用我们之前创建的帖子包装器类型 (PostListContainerModel) 修复 decoderColl

decoderColl : Decoder PostListContainerModel
decoderColl =
  Decode.map
    PostListContainerModel
    (Decode.field "posts" (Decode.list postDecoder))