2
votes

I'm trying to learn the Aeson library in Haskell. Right now I'm trying to parse a simple JSON file which look like this

{
    "Meta Data": {
        "1: Symbol": "MSFT",
        "2: Indicator": "Relative Strength Index (RSI)",
        "3: Last Refreshed": "2018-10-15",
        "4: Interval": "weekly",
        "5: Time Period": 10,
        "6: Series Type": "open",
        "7: Time Zone": "US/Eastern Time"
    },
    "Technical Analysis: RSI": {
        "2018-10-15": {
            "RSI": "54.5653"
        },
        "2018-10-12": {
            "RSI": "63.0279"
        },
        "2018-10-05": {
            "RSI": "74.7519"
        },
        "2018-09-28": {
            "RSI": "72.1573"
        },
        "2018-09-21": {
            "RSI": "74.8123"
        },
        "2018-09-14": {
            "RSI": "66.7116"
        },
        "2018-09-07": {
            "RSI": "75.8051"
        },
..and so on

with the help of this tutorial on Aeson Aeson: the tutorial Specifically the "Nested records" section


This is what I've got so far.

{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards   #-}

module Tesst where

import           Data.Aeson
import qualified Data.ByteString.Lazy as B
import           Data.Time
import           GHC.Exts
import           GHC.Generics
import           Network.HTTP.Conduit (simpleHttp)

data TechinicalAnalysis = TechinicalAnalysis {
                   name :: String,
                   date :: String,
                   rsi  :: String
                   } deriving (Show, Generic)


instance FromJSON TechinicalAnalysis where
  parseJSON = withObject "RSI Quote" $
    \o -> do
      rsiQuote <- o        .: "Technical Analysis: RSI"
      date     <- rsiQuote .: "2018-10-16"
      rsi      <- date     .: "RSI"
      return TechinicalAnalysis {..}


main :: IO ()
main = do
  putStrLn "Which ticker? "
  symbolToQuote <- getLine
  d <- (eitherDecode <$> simpleHttp ("https://www.alphavantage.co/query?function=RSI&interval=weekly&time_period=10&series_type=open&apikey==FI2KMCSDSAE&symbol=" ++ symbolToQuote)) :: IO (Either String TechinicalAnalysis)
  case d of
    Left e   -> print e
    Right qt -> print (rsi qt)

My goal here is to get the latest "RSI" quote from the JSON file from the link. I'm not sure how to go about doing that right now, so for testing purposes I manually wroth the key "2018-10-16" in the parseJSON section.


The error msg I get running the code is

    • Couldn't match type ‘unordered-containers-0.2.9.0:Data.HashMap.Base.HashMap
                             Data.Text.Internal.Text Value’
                     with ‘[Char]’
      Expected type: String
        Actual type: Object
    • In the ‘date’ field of a record
      In the first argument of ‘return’, namely ‘TechinicalAnalysis {..}’
      In a stmt of a 'do' block: return TechinicalAnalysis {..}
   |
27 |       return TechinicalAnalysis {..}
   |              ^^^^^^^^^^^^^^^^^^^^^^^

Which I think is telling me that the response date got from date <- rsiQuote .: "2018-10-15" isn't what I expected.


Here you can find my previous questing and what I later figured out as an answer (different JSON file, parsed successfully)

1
Have you tried return (TechinicalAnalysis {..}) or return $ TechinicalAnalysis {..}?Mark Seemann
@MarkSeemann Just did, no luck :( Got the same erroruser6306428

1 Answers

2
votes

I solved the problem.

What .: returns has the type Object and not String

So instead of this

data TechinicalAnalysis = TechinicalAnalysis {
                   name :: String,
                   date :: String,
                   rsi  :: String
                   } deriving (Show, Generic)

I wroth this

newtype TechinicalAnalysis = TechinicalAnalysis {
                   rsi  :: String
                   } deriving (Show, Generic)

and it worked seamlessly.