【问题标题】:ELM parse nested jsonELM 解析嵌套的 json
【发布时间】:2017-01-25 21:52:54
【问题描述】:

我有一个包含多个可以嵌套的 cmets 的 json 数组。

示例:

[
  {
    "author": "john",
    "comment" : ".....",
    "reply": "",
  },
  {
    "author": "Paul",
    "comment" : ".....",
    "reply": [  
      {
        "author": "john",
        "comment" : "nested comment",
        "reply": [
          {
            "author": "Paul",
            "comment": "second nested comment"
          }
        ]
      },
      {
        "author": "john",
        "comment" : "another nested comment",
        "reply": ""
      }
    ]
  },
  {
    "author": "Dave",
    "comment" : ".....",
    "reply": ""
  },
]

所以它是一个评论列表,每个评论都可以有一个回复,回复的数量是无限的。 使用Json.Decode.list我可以解码第一级评论,但是如何检查是否有回复然后再次解析?

这是我尝试做的简化版本。我实际上是在尝试解码 reddit cmets。 exemple

【问题讨论】:

  • 你不想有一个“再次”解析的心理模型。您想为同一字段使用中间值或不同的解码器。看看package.elm-lang.org/packages/elm-lang/core/latest/…。它允许根据已解码的数据切换子解码器。还有oneOf,允许您解析空字符串(您可以手动将其转换为空的回复列表)或嵌套回复。

标签: json parsing decode elm reddit


【解决方案1】:

Elm 不允许您创建递归记录类型别名,因此您必须为 Customer 使用联合类型。您可能还需要一个方便的函数来创建用户,以便您可以使用Json.map3

您的示例 json 有一个奇怪之处:有时 reply 是一个空字符串,有时它是一个列表。您需要一个特殊的解码器将该字符串转换为空列表(假设空列表在此上下文中与空列表同义)。

由于您有递归类型,因此您需要使用lazy 对子 cmets 进行解码以避免运行时错误。

import Html exposing (Html, text)
import Json.Decode as Json exposing (..)


main : Html msg
main =
    text <| toString <| decodeString (list commentDecoder) s


type Comment
    = Comment
        { author : String
        , comment : String
        , reply : List Comment
        }


newComment : String -> String -> List Comment -> Comment
newComment author comment reply =
    Comment
        { author = author
        , comment = comment
        , reply = reply
        }


emptyStringToListDecoder : Decoder (List a)
emptyStringToListDecoder =
    string
        |> andThen
            (\s ->
                case s of
                    "" ->
                        succeed []

                    _ ->
                        fail "Expected an empty string"
            )


commentDecoder : Decoder Comment
commentDecoder =
    map3 newComment
        (field "author" string)
        (field "comment" string)
        (field "reply" <|
            oneOf
                [ emptyStringToListDecoder
                , list (lazy (\_ -> commentDecoder))
                ]
        )


s =
    """
[{
  "author": "john",
  "comment": ".....",
  "reply": ""
}, {
  "author": "Dave",
  "comment": ".....",
  "reply": ""
}, {
  "author": "Paul",
  "comment": ".....",
  "reply": [{
    "author": "john",
    "comment": "nested comment",
    "reply": [{
      "author": "Paul",
      "comment": "second nested comment",
      "reply": ""
    }]
  }, {
    "author": "john",
    "comment": "another nested comment",
    "reply": ""
  }]
}]
"""

(您的 json 在其他方面也有点偏离:列表的最后部分后面有几个额外的逗号,并且缺少一个 reply 字段)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-25
    • 2020-05-02
    • 2019-01-24
    • 1970-01-01
    相关资源
    最近更新 更多