I'm new to Haskell as well as Stack. This would be one of my first few programs in Haskell. Hence, unable to make it work correctly so far.
With the help of a small Haskell program, a JSON file (a short summary of statistics data from a website - in nested JSON format) was obtained. I got that inside 'App' folder of that stack project.
In the next program/stack-project, we try to parse the data.json (obtained in the previous program) and get only certain portion of that statistics displayed/printed in ghci - in a list format (with the help of forM_ [decoded-JSON's-certain-portion-of-data-in-list-format] (print . name)). Since the 'decode-JSON' function (from Data.Aseon) would produce results in Maybe format, we also do pattern-matching to display 'Error - loading data' in case the result is nothing; And, do forM_ when there is Just data.
My issue is that - Code compiles; But, says 'Error - loading failed' even when I had placed the data.json inside this particular stack project's folder.
- have added 'import System.IO' in Main module.
- have added "Data-files: (/n)-data.json" inside package.yaml - at the top, right below the 'extra-source-files' details.
I didn't make any manual update inside cabal file. Stack wouldn't let me do any manual change in cabal file and asks me to delete either cabal or package.yaml. There are no such errors/warnings thrown by stack, when package.yaml is updated with the details of 'Dependencies and Extensions' details,etc. Hence, I updated this data.json info in package.yaml.
(Though I am not sure which is the right location inside stack-proj-folder, where the input data ought to be placed.
I tried placing it as one of the elements in the root folder of the project, along with package.yaml, cabal file and stack.yaml etc;
I also placed a copy of data.json file - inside 'app' folder - along with Main.hs file (as that's where the output what placed by stack in the previous program. Hence, assumed stack might look consider this folder for input/output files, though I'm not sure and it doesn't seem to work as expected);
I also made one additional folder named 'data' (just like src, app and test) , and have placed a copy of data.json file inside that. Though I haven't given any description inside package.yaml for this new 'data' folder, as I wasn't sure of the right way to do it)
But, irrespective of all these places I have tried placing the input data.json file - for stack to access and read, it doesn't seem to work so. The compiled code always returns 'Error loading data' - indicating the decodeJSON function returned nothing/no-data - even though the file/data-format is valid. (It was not manually prepared file - where the error could occur due to manual formatting; It was just a system produced JSON file data from a website. And, it has valid data for decoding)
I am attaching
- package.yaml update
- data.json file's data
- Main module code here for reference.
At the top of packagae.yaml :
extra-source-files:
- README.md
- ChangeLog.md
data-files:
- data.json
The data in the file named "data.json" :
{"metadata":{"resultset":{"offset":1,"count":11,"limit":25}},"results":[{"uid":"gov.noaa.ncdc:C00861","mindate":"1763-01-01","maxdate":"2021-07-02","name":"Daily Summaries","datacoverage":1,"id":"GHCND"},{"uid":"gov.noaa.ncdc:C00946","mindate":"1763-01-01","maxdate":"2021-06-01","name":"Global Summary of the Month","datacoverage":1,"id":"GSOM"},{"uid":"gov.noaa.ncdc:C00947","mindate":"1763-01-01","maxdate":"2021-01-01","name":"Global Summary of the Year","datacoverage":1,"id":"GSOY"},{"uid":"gov.noaa.ncdc:C00345","mindate":"1991-06-05","maxdate":"2021-07-02","name":"Weather Radar (Level II)","datacoverage":0.95,"id":"NEXRAD2"},{"uid":"gov.noaa.ncdc:C00708","mindate":"1994-05-20","maxdate":"2021-07-02","name":"Weather Radar (Level III)","datacoverage":0.95,"id":"NEXRAD3"},{"uid":"gov.noaa.ncdc:C00821","mindate":"2010-01-01","maxdate":"2010-01-01","name":"Normals Annual/Seasonal","datacoverage":1,"id":"NORMAL_ANN"},{"uid":"gov.noaa.ncdc:C00823","mindate":"2010-01-01","maxdate":"2010-12-31","name":"Normals Daily","datacoverage":1,"id":"NORMAL_DLY"},{"uid":"gov.noaa.ncdc:C00824","mindate":"2010-01-01","maxdate":"2010-12-31","name":"Normals Hourly","datacoverage":1,"id":"NORMAL_HLY"},{"uid":"gov.noaa.ncdc:C00822","mindate":"2010-01-01","maxdate":"2010-12-01","name":"Normals Monthly","datacoverage":1,"id":"NORMAL_MLY"},{"uid":"gov.noaa.ncdc:C00505","mindate":"1970-05-12","maxdate":"2014-01-01","name":"Precipitation 15 Minute","datacoverage":0.25,"id":"PRECIP_15"},{"uid":"gov.noaa.ncdc:C00313","mindate":"1900-01-01","maxdate":"2014-01-01","name":"Precipitation Hourly","datacoverage":1,"id":"PRECIP_HLY"}]}
Code :
module Main where
import Data.Aeson
import qualified Data.Text as T
import qualified Data.ByteString.Lazy as B
import qualified Data.ByteString.Lazy.Char8 as BC
import GHC.Generics
import Control.Monad
import Control.Applicative
import System.IO
Data Type declaration for the data inside data.json :
data NOAAResult = NOAAResult
{ uid :: T.Text
, mindate :: T.Text
, maxdate :: T.Text
, name :: T.Text
, datacoverage :: Int
, resultId :: T.Text
} deriving Show
instance FromJSON NOAAResult where
parseJSON (Object v) =
NOAAResult <$> v .: "uid"
<*> v .: "mindate"
<*> v .: "maxdate"
<*> v .: "name"
<*> v .: "datacoverage"
<*> v .: "id"
data Resultset = Resultset
{ offset :: Int
, count :: Int
, limit :: Int
} deriving (Show,Generic)
instance FromJSON Resultset
data Metadata = Metadata
{
resultset :: Resultset
} deriving (Show,Generic)
instance FromJSON Metadata
data NOAAResponse = NOAAResponse
{ metadata :: Metadata
, results :: [NOAAResult]
} deriving (Show,Generic)
instance FromJSON NOAAResponse
IO actions :
printResults :: Maybe [NOAAResult] -> IO ()
printResults Nothing = print "error loading data"
printResults (Just results) = do
forM_ results (print . name)
main :: IO ()
main = do
jsonData <- B.readFile "data.json"
let noaaResponse = decode jsonData :: Maybe NOAAResponse
let noaaResults = results <$> noaaResponse
printResults noaaResults
Would be helpful to know the right place and right procedure to place input data file in haskell-stack.
Also, after placing the data file in the respective folder/path, what updates need to be made in config files (like cabal (or) package.yaml) and in the code (like import System.IO) - so that the haskell program would have no issue in identifying the input data file from the stack-project folder and process it fine. ( As in my case, it gives 'Error loading data' message - even when the data.json input file is placed inside stack-proj folder. Hence, I assume, I am missing something to do it right)
Requesting for guidance/help.
Thank you.