我正在嘗試決議如下所示的 JSON blob:
"{\"order_book\":{\"asks\":[[\"0.06777\",\"0.00006744\"],[\"0.06778\",\"0.01475361\"], ... ]],\"bids\":[[\"0.06744491\",\"1.35\"],[\"0.06726258\",\"0.148585363\"], ...]],\"market_id\":\"ETH-BTC\"}}"
那些成對的數字串列實際上要長得多。我用橢圓代替了它們的尾巴。
這是我的代碼:
{-# LANGUAGE OverloadedStrings #-}
module Demo where
import Data.Aeson
import Data.ByteString.Lazy hiding (putStrLn)
import Data.Either (fromLeft)
import Network.HTTP.Request
data OrderBook = OrderBook
{ orderBook_asks :: [[(Float,Float)]]
, orderBook_bids :: [[(Float,Float)]]
, orderBook_marketId :: String
}
instance FromJSON OrderBook where
parseJSON = withObject "order_book" $ \v -> OrderBook
<$> v .: "asks"
<*> v .: "bids"
<*> v .: "market_id"
demo :: IO ()
demo = do
r <- get "https://www.buda.com/api/v2/markets/eth-btc/order_book"
let d = eitherDecode $ fromStrict $ responseBody r :: Either String OrderBook
putStrLn $ "Here's the parse error:"
putStrLn $ fromLeft undefined d
putStrLn $ "\n\nAnd here's the data:"
putStrLn $ show $ responseBody r
這就是跑步demo帶給我的東西:
Here's the parse error:
Error in $: key "asks" not found
And here's the data:
"{\"order_book\":{\"asks\":[[\"0.06777\",\"0.00006744\"],[\"0.06778\",\"0.01475361\"], ... ]],\"bids\":[[\"0.06744491\",\"1.35\"],[\"0.06726258\",\"0.148585363\"], ...]],\"market_id\":\"ETH-BTC\"}}"
“asks”鍵在我看來很明顯——它是嵌套在“order_book”鍵下的第一個鍵。
uj5u.com熱心網友回復:
密鑰存在,但它被包裹在另一個嵌套物件中,因此您必須先解開外部物件才能決議密鑰。
執行此操作的最小差異方法可能只是行內:
instance FromJSON OrderBook where
parseJSON = withObject "order_book" $ \outer -> do
v <- outer .: "order_book"
OrderBook
<$> v .: "asks"
<*> v .: "bids"
<*> v .: "market_id"
盡管您可能想考慮引入另一種包裝型別。這實際上取決于您擁有的資料格式的語意。
我猜你可能假設這是withObject "order_book"會做的,但事實并非如此。的第一個引數withObject只是被決議物件的可讀名稱,用于創建錯誤訊息。通常,該引數應命名正在決議的型別- 即withObject "OrderBook"。請參閱檔案。
另外,我認為您的asks和bids欄位輸入錯誤。
首先,您的 JSON 輸入看起來應該是元組陣列,但您的 Haskell 型別表示元組的雙重嵌套陣列。所以這將無法決議。
其次,您的 JSON 輸入將字串作為這些元組的元素,但您的 Haskell 型別說Float. 這也將無法決議。
根據您的 JSON 輸入,正確的型別應該是:
{ orderBook_asks :: [(String,String)]
, orderBook_bids :: [(String,String)]
或者,如果您真的想要浮點數,則必須從字串中決議它們:
instance FromJSON OrderBook where
parseJSON = withObject "order_book" $ \outer -> do
v <- outer .: "order_book"
OrderBook
<$> (map parseTuple <$> v .: "asks")
<*> (map parseTuple <$> v .: "bids")
<*> v .: "market_id"
where
parseTuple (a, b) = (read a, read b)
(請注意,此??代碼不可復制和粘貼:我read用于將字串決議為浮點數,如果字串格式錯誤,它將在運行時崩潰;在實際程式中,您應該使用更好的決議方式)
uj5u.com熱心網友回復:
withObject "order_book"不查看 key 的值"order_book"。實際上,"order_book"除了出現在錯誤訊息中之外,該引數被忽略了;實際上你應該在withObject "OrderBook"那里。
withObject所做的只是確認你所擁有的是一個物件。然后它繼續使用該物件查找鍵"asks","bids"并且"market_id"- 但在此級別唯一存在的鍵是order_book。
解決方案是僅將此決議器與{"asks":[["0.06777"...]...]...}物件一起使用。無論如何,"order_book"密鑰都不會提供任何資訊,除非那里還存在其他密鑰。你可以用另一個 Haskell 型別和它自己的FromJSON實體來表示那個外部物件。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/437095.html
