0

I have trouble parsing the Tag in the following JSON structure. The parser works only when i declare it to be tags :: !Array It fails when i declare it as tags :: [Tag]

Why?

{
  "response": {
    "status": "ok",
    "results": [
      {
        "type": "article",
        "fields": {
          "wordcount": "497"
        },
        "tags": [
          {
            "id": "profile/barryglendenning"
          }
        ]
      }
    ]
  }
}



data Field = Field{
    wordcount :: Int
} deriving (Show)

instance FromJSON Field where
    parseJSON (Object o) = Field <$> (o .: "wordcount")
    parseJSON _ = mzero


data Tag = Tag{
    id :: Text
} deriving (Show)

instance FromJSON Tag where
    parseJSON (Object o) = Tag <$> (o .: "id")
    parseJSON _ = mzero

data SearchResult = SearchResult {
    type:: Text,
    field :: Field,
    tags  :: !Array
} deriving (Show)

instance FromJSON SearchResult where
    parseJSON (Object o) = do
        let t1 = o .: "type"
        let t2 = o .: "fields"
        let t3 = o .: "tags"
        SearchResult <$> t1 <*> t2 <*> t3
    parseJSON _ = mzero


data ContentrResult = ContentrResult {
    results :: [SearchResult],
    status  :: Text
} deriving (Show)

instance FromJSON ContentrResult where
    parseJSON (Object o) = do
        r <- o .: "response"
        ContentrResult <$> r .: "results"
                       <*> r .: "status"
    parseJSON _ = mzero
5
  • 2
    What is the exact error you are getting? Commented Aug 14, 2016 at 20:29
  • It has probably nothing to do with your problem, but I would not name a record field id, because then you would have an ambiguity with the prelude. Commented Aug 14, 2016 at 21:55
  • By the way, naming a field type is a syntax error Commented Aug 14, 2016 at 22:12
  • There is no error, i just get a nothing as return Commented Aug 14, 2016 at 22:31
  • It works here, modulo the errors I already mentioned, plus the type mismatch for wordcount, parsed as an Int when it is a string in json. I wish aeson could provide Either instead of Maybe. Commented Aug 14, 2016 at 22:48

1 Answer 1

2

Nothing isn't a very useful for debugging is it?

I managed to get your example JSON parsing the tags as a [Tag]. I wonder if your error could be related to the wordcount field being a String in the JSON rather than a Number.

Here is a more-or-less self-contained example where I changed the example JSON wordcount to a number:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}

module Main where

import Lib (str)

import Control.Monad (mzero)
import Data.Aeson
import qualified Data.ByteString.Lazy.Char8 as LBSC
import Data.Text

data Field = Field {
  wordcount :: Int
} deriving (Show)

instance FromJSON Field where
  parseJSON (Object o) = Field <$> o .: "wordcount"
  parseJSON _ = mzero

data Tag = Tag {
  id :: Text
} deriving (Show)

instance FromJSON Tag where
  parseJSON (Object o) = Tag <$> (o .: "id")
  parseJSON _ = mzero

data SearchResult = SearchResult {
  typ :: Text,
  fields :: Field,
  tags :: [Tag]
} deriving (Show)

instance FromJSON SearchResult where
  parseJSON (Object v) = SearchResult <$> v .: "type" <*> v .: "fields" <*> v .: "tags"
  parseJSON _ = mzero

data ContentrResult = ContentrResult {
  results :: [SearchResult],
  status :: Text
} deriving (Show)

instance FromJSON ContentrResult where
  parseJSON (Object v) = ContentrResult <$> v.: "results" <*> v .: "status"
  parseJSON _ = mzero

data Response = Response {
  response :: ContentrResult
} deriving (Show)

instance FromJSON Response where
  parseJSON (Object v) = Response <$> v .: "response"
  parseJSON _ = mzero

responseJson :: String
responseJson = [str|
  {
    "response": {
      "status": "ok",
      "results": [
        {
          "type": "article",
          "fields": {
            "wordcount": 497
          },
          "tags": [
            {
              "id": "profile/barryglendenning"
            }
          ]
        }
      ]
    }
  }
|]

main :: IO ()
main = do
  print r
  putStrLn ""
    where
      r :: Maybe Response
      r = decode (LBSC.pack responseJson)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.