본문 바로가기

Lang

[Python] jsonbender를 이용한 json 포맷 변환

DB 데이터를 Json 포맷으로 전환할 일이 생겨서 pandas 라이브러리로 간단하게 처리해봤다.

df = pd.read_sql_query(...)

if df.empty:
	return ''
else:
	return df.to_json(orient='records')

회사 일이란게 이렇게 쉽게 끝나는 경우가 있던가. 역시나 json 포맷이 플랫한 형태가 아니라 서브 노드가 있는 형태로 변경 되었다.

가령 SQL 로 추출한 DataFrame 을 to_json 으로 직접 변환하면 아래와 같은 형태로 변환된다.

[{"No": 1, "MakerCd": "abc", "Lat"": 10, "Lng": 20, "Contact": null}, ...]

이걸 아래처럼 변경(null 로 표시된 건 ""로 변환까지 포함)해달라는 요청.

[{"No": 1, "MakerCd": "abc", "Address": {"Location": {"Lat"": 10, "Lng": 20}, "Contact": ""}, ...]

json 을 dictionary 타입으로 바꾼 후 조작하면 되긴 하겠지만 그보다는 깔끔한 방법이 없을까 찾다가 jsonbender 를 발견했다.

github 페이지의 사용예만 봐도 간단한 사용은 어렵지 않은 편. 다만 list 형태일 때 예가 좀 헷갈렸는데 일단 ForallBend 이용하니 원하는 결과 구할 수 있었다.

다음은 jsonbender 적용하고 null 인 값들 공백 문자로 처리한 것까지 포함해서 구현 코드 를 쉽게 볼 수 있도록 살짝 편집한거.

import json
from jsonbender import bend, S
from jsonbender.list_ops import ForallBend
import pandas as pd

MAPPING = {
  'TYPE1': ForallBend({
  'No': S('No'),
  'MakerCd': S('MakerCd'),
  'Address': {'Location': {Lat': S('Lat'), 'Lng': S('Lng')}},
  'Contact': S('Contact'),
  })
}

def generate_json(type_id, json_str):
	df_json = json.loads(json_str)
	result = bend(MAPPING[type_id], df_json)
	return json.dumps(result)

df = pd.read_sql_query(...)
df.replace([None], "", inplace=True)
df_json = df.to_json(orient='records')
generate_json('TYPE1', df_json)

주) 이건 여러 경우를 테스트해보지 않아서 확실한건 아닌데 DB 데이터를 jsonbender 로 매핑 하려면 sql 문에서 alias 를 사용해서 명시적으로 컬럼명을 지정해주어야만 했다.

가령 다음과 같은 식으로 as 써주고 alias 는 꼭 쌍따옴표 처리해 줘야만(홑따옴표도 안됨) 매핑 때 제대로 인식되었다.

SELECT ... as "No", ... as "MakerCd" ... FROM ...

 이게 내 소스의 다른 부분 때문의 영향인지 애매하긴한데 어쨌거나 내 경우는 쌍따옴표 처리가 꼭 필요했음.