2017-10-17 46 views
1

我有不幸數據一起工作:埃宋與數組的數組,其中一些是空

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

條目允許爲任一空數組,或大小的4的陣列中的數據。

,我想解析爲:

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]附近添加一個額外的類型,並將子陣列轉換爲列表和pat tern匹配[],並將非空案例分配給ResultRow解析器,但我根本無法將其編譯並丟失在錯誤消息中。

理想情況下,我想有一些跳過空數組的方式,因爲它們只是數據中的噪聲。我無法控制數據的製作者。

+2

在這種情況下,我不會使用通用的json解析器,而是使用來自aeson的組合器自己編寫它! – epsilonhalbe

+0

你是說這對於通用的json解析器來說是不可能的/不可行的,或者你只是不知道如何去做,因此在評論中而不是回答中推薦組合器?你有沒有什麼閱讀材料可以用你提到的組合器來探索與我有些相似的數據? – dsvensson

+0

嘗試可能[ResultRow]而不是[可能ResultRow] – madnight

回答

2

dsvensson,我困惑的是,這並不「只是工作」開箱即用的,因爲這兩個[a]Maybe aFromJSON實例時a是。由於我已經花了太多時間在這方面,所以我不能提供解釋,但我可以提供解決方法。希望有更多知識的人能給出更好的答案。

而不是定義f_data[Maybe ResultRow],你可以定義一個newtype它包裝Maybe ResultRow

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

你可以給這類特殊FromJSON行爲:

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

顯然,這意味着ResultSet的變化:

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

爲了測試,我定義這個JSON文件:

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

它全部加載到GHCI,它看起來像它的工作:

*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的輸出以提高可讀性。

我相信你能弄清楚如何解開和過濾MaybeResultRow值的列表...

我偷用fromJSON和匹配上Successthis answer的解決方案。