2016-07-05 4 views
2

REST 서버에서 복잡한 형식의 JSON 응답을 사용하고 있습니다. 그것들을 디코딩하기 위해 서로 다른 중첩 된 객체를 다루기 위해 몇 가지 데이터 유형이 있습니다. 예 :Aeson은 문자열 또는 int 일 수있는 JSON 객체를 디코딩합니다.

... Other types ... 

data Profile = 
    Profile { fields :: [KVPair] 
    } deriving (Show) 

instance FromJSON Profile where 
    parseJSON (Object v) = 
    Profile <$> v .: "Fields" 
    parseJSON _ = mzero 

data KVPair = 
    KVPair { key :: Int 
     , value :: String 
    } deriving (Show) 

instance FromJSON KVPair where 
    parseJSON (Object v) = 
    KVPair <$> v .: "Key" 
      <*> v .: "Value" 
    parseJSON _ = mzero 

최종 KVPair 유형을 제외한 모든 기능이 작동합니다. 내 JSON 객체에는 모두 정수 키가 있습니다. 그러나, 값은 정수 또는 문자열이 될 수 있습니다 :

 { 
     "Key": 0, 
     "Value": "String Value!" 
     }, 
     { 
     "Key": 1, 
     "Value": 42 
     } 

지금 내가 StringInt 구성되어 내 값 디코딩에 다른 합계 유형을 추가 할 수도있을 것 같군요,하지만 나는 전체를 추가하지 않도록하는 것을 선호 그저 새로운 유형입니다. Aeson은이 시나리오를 처리하는 간단한 방법이 있습니까?

답변

4

두 가지 간단한 수정이 있습니다. 하나는 간단히 작성하는 것입니다.

data KVPair = KVPair { key :: Int, value :: Value } 

다른 모든 코드는 동일하게 유지하십시오. 소비자는 Value을 확인하여 문자열 y인지 숫자 y인지 확인해야합니다.

아마도 더 나은 방법은 원하는 형식으로 변환되는 두 개의 대체 파서를 제공하는 것입니다. 예를 들어,있는 그대로 당신의 KVPair 정의를 유지, 하나는 두 세계의 최고 그것이 String 또는 주변 Int 값의 다른 종류를 거부 할 수 있는지 여부에 대한 정보를 유지하는 것입니다

showInt :: Int -> String 
showInt = show 

instance FromJSON KVPair where 
    parseJSON (Object v) 
     = KVPair 
     <$> v .: "Key" 
     <*> (v .: "Value" <|> (showInt <$> v .: "Value")) 

작성할 수 있습니다; 예 :

data KVPair = KVPair { key :: Int, value :: Either String Int } 

instance FromJSON KVPair where 
    parseJSON (Object v) 
     = KVPair 
     <$> v .: "Key" 
     <*> ( (Left <$> v .: "Value") 
      <|> (Right <$> v .: "Value") 
      ) 
+0

대체 구문 분석 메소드를 올바르게 이해하면 정수 값을 문자열 유형으로 강제 변환 할 수 있습니까? 따라서 "Value": 3은 KVPair {value = "3"}와 같은 것으로 변환됩니까? – jkeuhlen

+2

@jkeuhlen 정확히 말하자면 "강제 변환"은 여기에 적용되지 않는 하스켈의 특정한 의미를 가지고 있습니다 - "변환"또는 "예쁘게 인쇄"가 더 정확할 것입니다. –

1

모든 JSON 값이 될 수있는 필드가있는 객체로 작업하려면 Aeson 값 유형을 사용해야합니다.

+0

개체는 이미 Aeson의 HashMap입니다. 필요한 가치 만 조회하면됩니다. 그게 충분하지 않다면 JSON을 하나의 String Int로 구문 분석 할 수 있습니다. – dysinger