2017-10-17 31 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的解决方案。