RESTful API에서 JSON을 구문 분석하려고합니다. 반환 된 JSON은 중첩되어 있으며 특정 필드를 포함 할 수도 있고 포함하지 않을 수도 있습니다. 당신이 볼 수 있듯이, JSON 스키마는 location
, arrival
및 queryTime
포함하는 resultSet
시작Aeson을 사용하여 Haskell에서 중첩 JSON 구문 분석
{
resultSet : {
location : [{
desc : "Tuality Hospital/SE 8th Ave MAX Station",
locid : 9843,
dir : "Eastbound",
lng : -122.978016886765,
lat : 45.5212880911494
}
],
arrival : [{
detour : false,
status : "estimated",
locid : 9843,
block : 9024,
scheduled : "2014-03-02T16:48:15.000-0800",
shortSign : "Blue to Gresham",
dir : 0,
estimated : "2014-03-02T16:48:15.000-0800",
route : 100,
departed : false,
blockPosition : {
at : "2014-03-02T16:16:43.579-0800",
feet : 3821,
lng : -122.9909514,
trip : [{
progress : 171494,
desc : "Hatfield Government Center",
pattern : 140,
dir : 1,
route : 100,
tripNum : "4365647",
destDist : 171739
}, {
progress : 0,
desc : "Cleveland Ave",
pattern : 10,
dir : 0,
route : 100,
tripNum : "4365248",
destDist : 3577
}
],
lat : 45.5215368,
heading : 328
},
fullSign : "MAX Blue Line to Gresham",
piece : "1"
}, {
detour : false,
status : "estimated",
locid : 9843,
block : 9003,
scheduled : "2014-03-02T17:05:45.000-0800",
shortSign : "Blue to Gresham",
dir : 0,
estimated : "2014-03-02T17:05:45.000-0800",
route : 100,
departed : false,
blockPosition : {
at : "2014-03-02T16:34:33.787-0800",
feet : 3794,
lng : -122.9909918,
trip : [{
progress : 171521,
desc : "Hatfield Government Center",
pattern : 140,
dir : 1,
route : 100,
tripNum : "4365648",
destDist : 171739
}, {
progress : 0,
desc : "Cleveland Ave",
pattern : 10,
dir : 0,
route : 100,
tripNum : "4365250",
destDist : 3577
}
],
lat : 45.5216054,
heading : 345
},
fullSign : "MAX Blue Line to Gresham",
piece : "1"
}
],
queryTime : "2014-03-02T16:35:21.039-0800"
}
}
: 여기에 몇 가지의 예는 데이터를 반환합니다. location
은 차례로 위치 목록을 포함하고 arrival
에는 도착 목록이 포함되어 있고 queryTime
은 UTC 시간입니다. 그런 다음 arrival
은 blockPosition
을 포함 할 수 있으며 trip
등을 포함 할 수 있습니다. 둥지가 많이 있습니다. 선택 필드가 많이 있습니다.
이 모든 것을 유지하기 위해 일련의 새로운 데이터 유형을 만들었습니다. 데이터 유형은 비슷하게 중첩됩니다. 각 데이터 유형에 대해 Aeson 라이브러리의 FromJSON 인스턴스가 있습니다.
-- Data Type Definitions and FromJSON Instance Definitions ---------------------
data ResultSet
= ResultSet { locations :: LocationList
,arrivals :: ArrivalList
,queryTime :: String
} deriving Show
instance FromJSON ResultSet where
parseJSON (Object o) =
ResultSet <$> ((o .: "resultSet") >>= (.: "location"))
<*> ((o .: "resultSet") >>= (.: "arrival"))
<*> ((o .: "resultSet") >>= (.: "queryTime"))
parseJSON _ = mzero
data TripList = TripList {triplist :: [Trip]} deriving Show
instance FromJSON TripList where
parseJSON (Object o) =
TripList <$> (o .: "trip")
parseJSON _ = mzero
data LocationList = LocationList {locationList :: [Location]} deriving Show
instance FromJSON LocationList where
parseJSON (Object o) =
LocationList <$> (o .: "location")
parseJSON _ = mzero
data Location
= Location { loc_desc :: String
,loc_locid :: Int
,loc_dir :: String
,loc_lng :: Double
,loc_lat :: Double
} deriving Show
instance FromJSON Location where
parseJSON (Object o) =
Location <$> (o .: "desc")
<*> (o .: "locid")
<*> (o .: "dir")
<*> (o .: "lng")
<*> (o .: "lat")
parseJSON _ = mzero
data ArrivalList = ArrivalList {arrivalList :: [Arrival]} deriving Show
instance FromJSON ArrivalList where
parseJSON (Object o) =
ArrivalList <$> (o .: "arrival")
parseJSON _ = mzero
data Arrival
= Arrival { arr_detour :: Bool
,arr_status :: String
,arr_locid :: Int
,arr_block :: Int
,arr_scheduled :: String
,arr_shortSign :: String
,arr_dir :: Int
,estimated :: Maybe String
,route :: Int
,departed :: Bool
,blockPosition :: Maybe BlockPosition
,fullSign :: String
,piece :: String
} deriving Show
instance FromJSON Arrival where
parseJSON (Object o) =
Arrival <$> (o .: "detour")
<*> (o .: "status")
<*> (o .: "locid")
<*> (o .: "block")
<*> (o .: "scheduled")
<*> (o .: "shortSign")
<*> (o .: "dir")
<*> (o .:? "estimated")
<*> (o .: "route")
<*> (o .: "departed")
<*> (o .:? "blockPosition")
<*> (o .: "fullSign")
<*> (o .: "piece")
parseJSON _ = mzero
data BlockPosition
= BlockPosition { bp_at :: String
,bp_feet :: Int
,bp_lng :: Double
,bp_trip :: Trip
,bp_lat :: Double
,bp_heading :: Int
} deriving Show
instance FromJSON BlockPosition where
parseJSON (Object o) =
BlockPosition <$> (o .: "at")
<*> (o .: "feet")
<*> (o .: "lng")
<*> (o .: "trip")
<*> (o .: "lat")
<*> (o .: "heading")
parseJSON _ = mzero
data Trip
= Trip { trip_progress :: Int
,trip_desc :: String
,trip_pattern :: Int
,trip_dir :: Int
,trip_route :: Int
,trip_tripNum :: Int
,trip_destDist :: Int
} deriving Show
instance FromJSON Trip where
parseJSON (Object o) =
Trip <$> (o .: "progress")
<*> (o .: "desc")
<*> (o .: "pattern")
<*> (o .: "dir")
<*> (o .: "route")
<*> (o .: "tripNum")
<*> (o .: "destDist")
parseJSON _ = mzero
이제 문제는 데이터를 쉽게 찾을 수 있다는 것입니다. 나는
json <- getJSON stopID
putStrLn (show (decode json :: (Maybe Value)))
에 의해 원시 JSON을 표시 할 수 있습니다하지만이 ResultSet의 데이터를 얻을 때, 그것은 Nothing
와 함께 실패합니다. 내가 중첩 된 데이터를 제거하고 간단 FromJSON의 데이터 유형 및 인스턴스에서 필드를 제거합니다 (queryString
필드를 얻기 위해 시도하는 경우
putStrLn (show (decode json :: Maybe ResultSet))
그러나, 성공 및 쿼리 문자열 필드를 반환합니다.
data ResultSet
= ResultSet {
queryTime :: String
} deriving Show
instance FromJSON ResultSet where
parseJSON (Object o)
= ResultSet <$> ((o .: "resultSet") >>= (.: "queryTime"))
parseJSON _ = mzero
내가 잘못하고있는 것은 무엇입니까? 이것은 하스켈에서 JSON을 파싱하는 가장 쉬운 방법인가요?이 학생 (학생)의 총 멍청이입니다. 따라서 부드럽게하십시오.
문제는 당신의 파서가 약간의 오류가 어느 쪽이든 아마 또는 당신이하지 생각처럼 입력이 보이지 않습니다. 오류 메시지를 가져 와서 여기에 붙여 넣으려면 디코드 대신에 두 decode 함수를 사용해야합니다. – Reite
스타일 포인트 : ResultSet 용 parseJSON에서 ResultSet을 한 번 추출한 다음 질문을해야합니다. 동일한 값에 대해 세 번의 별도 조회가 수행됩니다. –
@Reite : 두 코드 중 하나를 사용하면 실제로 mzero 오류가 나타납니다.이것은 FromJSON 인스턴스가 옳지 않다는 것을 말해줍니다. 내 패턴 일치가'parseJSON _ = mzero' 패턴으로 떨어지는 것 같습니다. 하지만 왜? 들어오는 JSON을 검사했습니다. 위치 입력란이 있습니다. –