试图解析递归JSON,我是在正确的轨道上吗?

时间:2011-10-17 22:18:32

标签: json haskell recursion abstract-data-type

此问题与this问题有关。

以下是我希望通过JSON创建的数据类型:

data ProdObject = MKSpair (Text, Text)
                | MKSLpair (Text, [Text])
                | MKSOpair (Text, ProdObject)
                | MKObject ProdObject
                | End
                deriving Show

Here是我正在使用的数据的示例,以及整体的概括。

这是我的实例定义,导致错误。我使用this作为参考。我不确定错误是告诉我修复我的类型,还是我离开了。如果错误确实是直接的,我想要一些关于如何修复我的类型的建议,以及关于我可能做错什么但还没有注意到的任何建议。

instance FromJSON ProdObject where
  parseJSON (Object o) = MKObject <$> parseJSON o
  parseJSON (String s, String t)  = MKSpair (s, t)
  parseJSON (String s, Object o)  = MKSOpair (s, MKObject <$> parseJSON o)
  parseJSON (String s, Array a) = MKSLpair (s, V.toList a)
  parseJSON (Done d) = End
  parseJSON _        = mzero

这是我现在的错误:

ghcifoo> :load test
[1 of 1] Compiling Main             ( test.hs, interpreted )

test.hs:23:52:
    Couldn't match expected type `Value'
                with actual type `Data.Map.Map Text Value'
    Expected type: Value
      Actual type: Object
    In the first argument of `parseJSON', namely `o'
    In the second argument of `(<$>)', namely `parseJSON o'
Failed, modules loaded: none.

更新:我重做了我的数据类型,如果我是对的,我有一个幻像类型。如果我错了,回到绘图板

data ProdObject = MKSpair (Text, Text)
                | MKSLpair (Text, [Text])
                | MKSOpair (Text, ProdObject)
                | MKObject ProdObject (k,v)
                | End

此外,我已经在我的实例中反映了这种变化,尽管方式不完整。我提到这只是为了问我是否走在正确的轨道上。

parseJSON (Object (k,v)) = MKObject ...

如果我走在正确的轨道上,我想我可以弄清楚剩下的,或者至少问一个具体的问题。反馈任何人?

1 个答案:

答案 0 :(得分:1)

在这个等式中:

parseJSON (Object o) = MKObject <$> parseJSON o

o的类型为Map Text Value,但parseJSON的类型为Value -> Parser a,因此您显然无法将parseJSON应用于o。< / p>

此外,您在此处遇到类型错误:

parseJSON (String s, String t)  = MKSpair (s, t)

parseJSON的类型为Value -> Parser a,但您尝试与(Value, Value)匹配。

同样适用于这一行:

parseJSON (Done d) = End

Done不是Value类型的构造函数。


我无法理解为什么需要ProdObject类型递归;这是我如何解决这个问题:

data Outer = Outer {
  oName :: Text,
  oProducts :: M.Map Text Inner
} deriving Show

data Inner = Inner {
  iQA :: Text,
  iVM :: Text,
  iAvailable :: V.Vector Text
} deriving Show

instance FromJSON Outer where
    parseJSON (Object o) = Outer <$> o .: "name" <*> o .: "products"
    parseJSON _ = mzero

instance FromJSON Inner where
  parseJSON (Object o) = Inner <$> o .: "qa" <*> o .: "vm" <*> o .: "available"
  parseJSON _ = mzero

可以找到完整的代码列表on Github