1

I have a project where I need to parse JSON. I get a list of objects, but it's all contained inside the "data" key. Currently I have a little object to help me :

data StorageList = StorageList { sl :: [Storage] }

instance FromJSON StorageList where
  parseJSON = withObject "StorageList" $ \v -> StorageList
    <$> v .: "data"

Then I just use "sl" to get my actual list from the result.

It works perfectly fine, but I think we'll all agree that it's ugly. I imagine there must be an easier way to parse that [Storage] directly, somehow telling parseJSON to just start from inside data. Oh, and I'm using httpJSONEither from http-conduit, but if there is no way to do it with that I can change, I suppose.

EDIT : Here is storage :

data Storage = Storage { storageId     :: Text
                       , storageName   :: Text
                       , storageNode   :: Text
                       , storageSize   :: Int
                       , storageUsed   :: Int
                       } deriving Show

instance FromJSON Storage where
  parseJSON = withObject "Storage" $ \v -> Storage
    <$> v .: "id"
    <*> v .: "storage"
    <*> v .: "node"
    <*> v .: "maxdisk"
    <*> v .: "disk"

EDIT 2 : What I'm trying to parse has this look :

{
  "data":
  [
    {
      "id": "X",
      "storage": "X",
      ...
    },
    {
      "id": "Y",
      "storage": "Y",
      ...
    },
    ...
  ]
}

Hoping that'll be clearer. I'm using that ugly "StorageList" object to get rid of that data key wrapping everything, and it works, but I'm sure there must be a better way to handle it.

Ulrar
  • 895
  • 8
  • 17
  • Can't you make `Storage` be an instance `FromJSON` as well? – Willem Van Onsem Jun 10 '17 at 10:28
  • please include the definition of `Storage` - why not use a `newtype` and `derive (FromJSON)`, using `GeneralizedNewtypeDeriving` or if you must use a `data`-decaration - why not `derive Generic` and write the one-liner given in [`Data.Aeson` docs](https://hackage.haskell.org/package/aeson-1.2.0.0/docs/Data-Aeson.html) or make `StorageList` a simple `type StorageList = [Storage]` – epsilonhalbe Jun 10 '17 at 10:31
  • I added Storage. It is already an instance of FromJSON, or it wouldn't work. – Ulrar Jun 10 '17 at 11:04
  • I've read on it and I don't understand how newtype would help me. The current code I've pasted works perfectly fine, what I want is to remove StorageList object, which is just an intermediary type I use to take care of that "data" field. Basically what I need is a way to tell how to parse [Storage] instead of Storage, but you apparently can't do "instance FromJSON [Storage] where", it doesn't compile – Ulrar Jun 10 '17 at 14:34
  • @Ulrar You can indeed write `instance FromJSON [Storage] where ...` so if you get an error, either the error is unrelated, or you need to enable some extensions (`FlexibleInstances`). – user2407038 Jun 10 '17 at 20:08

0 Answers0