Null 값을 허용하는 Optional JSON 필드 파싱하기

Eunmin Kim·2024년 2월 16일
0

하스켈 일기

목록 보기
12/12

오늘 팁은 자료가 정말 없어서 오랜 삽질 끝에 얻은 결과라 귀하다. 하스켈로 realworld api를 만들고 있다. realworld api는 스펙이 정리되어 있어 그대로 보고 만들면 된다. 그 중 Update User라는 것을 만들고 있는데, 요청 본문에 User 필드 값을 넣어 사용자 정보를 업데이트하게 되어 있다. 요청 본문에 필드가 있는 값만 업데이트하게 설계한 것 같다. 예를 들어 요청 본문에 email, bio 만 있으면 두 값을 업데이트하면 되고 image 만 있으면 사용자 정보에서 image 만 바꿔주면 된다. 다른 필드는 모르겠지만 image 필드는 null을 허용하는 것 같다.

문제는 하스켈에서 JSON 옵셔널 필드를 어떻게 표현할 것이다. 뭐 여러가지 멋진 방법이 있지만 그것은 큰 문제는 아니다. 그냥 Maybe a로 해두고 요청 필드가 없으면 Nothing으로 하고 있으면 Just a로 하면 된다. 그럼 null 인 경우와 필드가 없는 경우는 어떻게 구분하는가? 그것도 더 멋진 방법이 있지만 그냥 Maybe (Maybe a)로 중첩해서 처리하면 된다. 최상위 Maybe는 필드가 있냐 없냐고 안 쪽에 값은 nullable이냐 아니냐를 나타내면 된다. 그래서 null 값이면 Just Nothing, 필드가 없으면 Nothing으로 하면된다.

하스켈은 JSON 변환할 때 Aeson 패키지를 쓴다. Aeson에도 옵셔널 필드를 지원한다. (.:?)와 (.:!) 로 parseJSON 할 때 JSON 객체에서 값을 조회해 볼 수 있다. nullable한 옵셔널 필드를 처리하기 위해서 (.:!)를 쓰면 된다. (.:!)이고 결과 타입이 Maybe (Maybe a)라면 필드가 없을 때 Nothing, 값이 null일 때는 Just Nothing, 값이 있을 때는 Just (Just a) 값을 준다.

data UpdateUserInput = UpdateUserInput
  { email :: Maybe Text,
    username :: Maybe Text,
    password :: Maybe Text,
    bio :: Maybe Text,
    image :: Maybe (Maybe Text)
  }
  deriving (Show, Generic)
  
instance FromJSON UpdateUserInput where
  parseJSON = withObject "UpdateUserInput" $ \value -> do
    UpdateUserInput
      <$> value
      .:! "email"
      <*> value
      .:! "username"
      <*> value
      .:! "password"
      <*> value
      .:! "bio"
      <*> value
      .:! "image"

문제 해결에 도움을 주신 장준영님께 감사드립니다.

profile
Functional Programmer @Constacts, Inc.

0개의 댓글