JSON
JSON은 파이썬의 다양한 객체를 직렬화(serialize)하는데 유용한 문법 중 하나이다. 객체가 복잡하게 구성되어 있더라도 강건하게 직렬화할 수 있고 직렬화된 결과물을 사람이 이해하기 쉽다는 점에서 강력한 장점을 보인다.
JSON 인코더-디코더 라이브러리
파이썬 객체를 JSON 형태의 문자열로 인코딩, JSON 형태의 문자열을 파이썬 객체로 디코딩해주는 여러 종류의 라이브러리 존재한다. 그 중, 파이썬 내장 라이브러리인 `json`과 패키지를 통해 설치가능한 `ujson`가 자주 사용된다.
JSON과 UJSON의 미세한 구현 차이
이 두 라이브러리는 문자열 객체를 인코딩하는 과정에서 미세한 차이점을 보인다. 예컨데, 문자열 객체 "http://www.naver.com"을 JSON으로 인코딩하면 다음과 같다.
Python 3.11.10 (main, Oct 3 2024, 07:29:13) [GCC 11.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import json
>>> import ujson
>>> s = "http://www.naver.com"
>>> json.dumps(s) # json 디코딩
'"http://www.naver.com"'
>>> print(json.dumps(s))
"http://www.naver.com"
>>> ujson.dumps(s) # ujson 디코딩
'"http:\\/\\/www.naver.com"'
>>> print(ujson.dumps(s))
"http:\/\/www.naver.com"
정리하자면, json의 경우, 인코딩하고자하는 문자열에 포함된 forwardslash(/)를 escaping 하지 않는다. 반면 ujson의 경우, forwardslash(/)를 escaping한다. 여기서 escaping을 한다는 것은, 특정 문자앞에 backslash(\)를 붙여 해당 문자가 특수문자임을 나타내는 행위를 의미한다.
구현 차이가 발생하게 된 원인
이러한 차이가 발생하게 된 이유로 옛날에 역사적으로, forwardslash를 escaping 해야하는 경우가 간혹 있었기 때문이라고 한다. 정확히는 나도 모르겠지만, javascript와 관련된 문제로 인해 forwardslash에 escaping을 해야했는데 해당 문제가 해결되면서 forwardslash는 escaping이 필요없다는 주류가 전파된 듯 하다. 따라서, 요즘은 기본값으로 escaping을 하지않지만 필요한 경우에 한해 escaping을 하는 걸로 변경됐다고 한다.
디코딩 구현 차이
디코딩에서는 escaping된 forwardslash나 escaping되지 않은 forwardslash 모두 forwardslash로 풀어낸다. 다음과 같은 예시를 보자.
>>> s
'http://www.naver.com'
>>> print(json.loads(json.dumps(s)))
http://www.naver.com
>>> print(json.loads(ujson.dumps(s)))
http://www.naver.com
>>> print(ujson.loads(json.dumps(s)))
http://www.naver.com
>>> print(ujson.loads(ujson.dumps(s)))
http://www.naver.com
놀랍게도 두 라이브러리를 섞어서 사용하더라도 큰 문제는 없어보인다. 이는 bashslash를 인코딩할 때, escaping을 해줘야하기 때문인 것으로 보인다.
섞어서 써도 괜찮을까?
지금까지의 실험결과에 따르면, 결국 인코딩된 문자열에 forwardslash가 escaping 되느냐 안되느냐의 차이가 주요하다. 이를 좀더 명확하게 보기 위해 다음과 같은 코드를 실행해보자.
>>> print(ujson.dumps(ujson.dumps(s)))
"\"http:\\\/\\\/www.naver.com\""
>>> print(json.dumps(json.dumps(s)))
"\"http://www.naver.com\""
ujson의 경우, forwardslash를 escaping하기 위해, bashslash가 추가되고, 두번째 디코딩에서 backslash 또한 escaping하기 위해, bashslash가 또 추가되는 것을 볼 수 있다. 물론 이를 두번 디코딩을 거치면 (json을 사용하든 ujson을 사용하든) 동일한 결과가 나오기는 한다. 이런저런 실험을 하면서 오류가 발생하지는 않을 것 같지만, 괜한 불안감이 생기는 건 어쩔 수 없는 것 같다. 다행히 별 문제는 없는 것처럼 보이지만 아예 모르고있는 것보다는 이러한 미세한 차이점이 있다는 걸 인지하고 있는게 좋지않을까 싶다. 개인적으로, json의 인코딩 결과가 사람이 읽기 더 좋은 것 같아 나는 json을 선호하는 편이다. 마지막으로, ujson은 pandas 데이터프레임을 json으로 직렬화하는데 기본값으로 사용되는 엔진이기 때문에, pandas 데이터프레임을 직렬화하는 to_json을 사용할 경우, forwardslash는 escaping된 채로 나온다.
참고자료
'Engineering' 카테고리의 다른 글
View를 리턴하는 것과 Copy를 리턴하는 것 (0) | 2024.12.24 |
---|---|
BrokenPipeError 분석 (0) | 2024.09.27 |
배열 내에 k번째로 작은 수 구하기 (0) | 2024.05.09 |
Instruction tuned model과 eos 토큰 (1) | 2024.02.27 |
Github Private Repo로 Fork하기 (0) | 2024.01.17 |