2017-10-17 8 views
1

비어있는 배열의 배열과 :아이손 일부는 내가 작업 할 불행한 데이터가

{ "name": "foo" 
, "data": [ [] 
      , ["a", "b", "c", 1] 
      , ["d", "e", "f", 2] ] } 

항목이 빈 배열, 또는 크기 네 가지의 배열이 될 수 있습니다 데이터를. 내가로 구문 분석하려는

:

data ResultRow = ResultRow Text Text Text Int deriving (Show, Generic) 

data ResultSet = 
    ResultSet { f_name :: Text 
      , f_data :: [Maybe ResultRow] } deriving (Show, Generic) 

다음은 빈 배열을 허용하지 않습니다 그러나 다음

customOptions = defaultOptions { fieldLabelModifier = drop 2 } 

instance FromJSON ResultRow where 
    parseJSON = genericParseJSON customOptions 
instance FromJSON ResultSet where 
    parseJSON = genericParseJSON customOptions 

오류 메시지는 다음과 같습니다

Left "Error in $[1].data[0]: When expecting a product of 4 values, encountered an Array of 0 elements instead" 

내가했습니다를 또한 [Maybe ResultRow] 주위에 여분의 유형을 넣으려고했는데 그 하위 배열을 목록과 팻으로 변환해야했습니다. tern이 []에 일치하고 공백이 아닌 경우를 ResultRow 파서로 보내면 컴파일 할 수 없으며 오류 메시지가 손실됩니다.

이상적으로는 데이터의 노이즈 일 뿐이므로 빈 배열을 건너 뛰는 방법이 필요합니다. 나는 데이터 생산자에 대한 통제권이 없다.

+2

이 경우에는 일반 json 파서를 사용하지 않고 대신 aeson의 연결자를 사용하여 직접 작성합니다! – epsilonhalbe

+0

일반 json 파서를 사용하면 불가능하거나 불가능하다는 말입니까? 아니면 어떻게 해야할지 모르기 때문에 답변이 아닌 주석으로 연결자를 추천 하시겠습니까? 당신이 언급 한 연결자를 사용하여 내가 가지고있는 비슷한 데이터를 탐구 해 볼 것을 제안 할 독서물이 있습니까? – dsvensson

+0

[ResultRow] 대신 [ResultRow]를 시도하십시오. – madnight

답변

2

dsvensson처럼, 나는 a 인 경우 [a]Maybe a 모두 FromJSON 인스턴스이기 때문에, 상자 밖으로 '그냥 작동'하지이 않는 것을 의아해 해요. 이 문제에 너무 많은 시간을 소비 했으므로 설명을 제공 할 수는 없지만 해결 방법을 제공 할 수 있습니다. 더 잘 알고있는 누군가가 더 나은 대답을 줄 수 있기를 바랍니다.

instance FromJSON MaybeResultRow where 
    parseJSON v = 
    case fromJSON v of 
     Success rr -> return $ MaybeResultRow $ Just rr 
     _   -> return $ MaybeResultRow Nothing 

이것은 분명히하는 것을 의미 :

newtype MaybeResultRow = MaybeResultRow (Maybe ResultRow) deriving (Show, Generic) 

당신은 이런 종류의 특별 FromJSON 동작을 제공 할 수 있습니다 :

대신 [Maybe ResultRow]f_data을 정의, 당신은 Maybe ResultRow가 랩하는 newtype 정의 할 수 있습니다 ResultSet의 변경 :

data ResultSet = 
    ResultSet { f_name :: Text 
      , f_data :: [MaybeResultRow] } deriving (Show, Generic) 
여기

*Lib Lib> decode myJson :: Maybe ResultSet 
Just (ResultSet { 
      f_name = "foo" 
     , f_data = [ 
        MaybeResultRow Nothing, 
        MaybeResultRow (Just (ResultRow "a" "b" "c" 1)), 
        MaybeResultRow (Just (ResultRow "d" "e" "f" 2))]}) 

, 내가 포맷 할 자유를 촬영했습니다 : 제대로 작동 것 같습니다, GHCi으로 모든로드

myJson :: ByteString 
myJson = 
    "{\ 
    \\"name\": \"foo\",\ 
    \\"data\": [\ 
     \[],\ 
     \[\"a\", \"b\", \"c\", 1],\ 
     \[\"d\", \"e\", \"f\", 2]\ 
    \]\ 
    \}" 

: 테스트하기 위해

, 나는이 JSON 문서를 정의 가독성을 높이기 위해 GHCi의 출력.

당신이 포장을 푸는 방법을 알아낼 MaybeResultRow 값의 목록을 필터링 할 수있는 신뢰

...

나는 this answer에서 SuccessfromJSON과 일치를 사용하는 솔루션을 훔쳤다.