2016-09-17 3 views
4

중첩 될 수있는 여러 주석이있는 json 배열이 있습니다.ELM은 중첩 된 json을 구문 분석합니다.

exemple :

[ 
    { 
    "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 주석을 디코딩하려고합니다. exemple

+0

원하지 않는 파싱의 정신 모형을 "다시"가질 수 있습니다. 동일한 필드에 대해 중간 값 또는 다른 디코더로 작업하려고합니다. http://package.elm-lang.org/packages/elm-lang/core/latest/Json-Decode#andThen을보십시오. 이미 디코딩 된 데이터에 따라 서브 디코더를 전환 할 수 있습니다. 'oneOf'도 있습니다. 빈 문자열 (수동으로 빈 응답 목록으로 변환 할 수 있음) 또는 중첩 응답을 구문 분석 할 수 있습니다. – pierrebeitz

답변

6

Elm은 재귀 레코드 유형 별명을 만들 수 없으므로 Customer에 대한 공용체 유형을 사용해야합니다. Json.map3을 사용할 수 있도록 사용자 생성을위한 편리한 함수가 필요할 수도 있습니다.

예 json이 이상합니다. 때때로 reply은 빈 문자열이며 때로는 목록입니다. 이 문자열을 빈 목록으로 바꾸려면 특별한 디코더가 필요합니다 (이 목록에서 빈 목록은 빈 목록과 동의어 임).

재귀 유형이 있으므로 런타임 오류를 피하기 위해 하위 주석을 디코딩 할 때 lazy을 사용해야합니다.

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 필드 중 하나를 쫓고없는)

관련 문제