Jost Do It.

그냥 IT해.

Programming/Python

[Python] json 출력 포맷 설정하기

그냥하Jo. 2023. 12. 19. 09:39
반응형

개요

API는 사용자 이해를 돕기 위해 일반적으로 docs문서를 제공한다.

특히 각 API마다 출력 결과 예시를 추가하면 사용자들에게 예상 결과, 에러 종류들을 안내하기 용이하다.

이 때 출력 결과 예시는 일반적으로 미리 출력해 저장한 json 데이터이다.

 

 

문제 상황

아래와 같이 출력 결과 예시 데이터는 미리 저장된 데이터원본 그대로이거나 원본을 간소화한 데이터다. 

{
  "api_name": "/api/v5/daily-stcok.json",
  "data": [
    {
      "date": "2020-03-02",
      "A005930": 55000,
      "A035720": 35125,
      "...": "..."
    },
    {
      "date": "2020-03-03",
      "A005930": 55400,
      "A035720": 35125,
      "...": "..."
    },
    {
      "...": "..."
    },
    {
      "date": "2021-02-15",
      "A005930": 84200,
      "A035720": 100760,
      "...": "..."
    }
  ],
  "error_msg": "",
  "request": "{query_params:[[item,close],[start_date,2020-03-01],[end_date,2021-02-15]],path_params:[]}",
  "return_code": "00"
}
  • 우리 회사 API docs에서는 예시 출력 결과가 너무 긴 경우 "..."과 같이 생략해 데이터를 제시하였다.

 

 

한편 예제 데이터는 아래와 같은 문제점이 존재한다.

  • API의 구조나 결과가 변경되면 기존 json 파일을 수정해줘야 하는데, API 수가 많아질수록 이를 수작업으로 하기 번거롭다
  • 예시 데이터가 오래된 경우에 API 실행 결과가 예시 데이터대로 나올지 확신할 수 없음

따라서 일정 주기로 API 출력 결과를 자동으로 간소화하여 포맷팅을 해주고 json 파일로 저장할 방법이 필요했다.

 

 

해결 방법

api 결과를 받으면 이를 간소화 해주는 함수를 아래와 같이 선언하였다.

import json

def parse_json_with_rules(json_str, indent=4):
    def custom_pairs_hook(pairs):
        if len(pairs) > 3:
            data =  {pairs[i][0]: pairs[i][1] for i in range(2)}
            data['...'] = '...'
            data[pairs[-1][0]] = pairs[-1][1]
            return data
        return dict(pairs)

    # JSON 문자열을 파이썬 객체로 로드
    data = json.loads(json_str, object_pairs_hook=custom_pairs_hook)

    # 로드된 데이터를 다시 JSON 형식의 문자열로 변환
    parsed_json_str = json.dumps(data, indent=indent)

    return parsed_json_str

# 테스트용 JSON 문자열
json_string = '{"key1": {"subkey1": "value1", "subkey2": "value2", "subkey3": "value3", "subkey4": "value4"}, "key2": {"subkey3": "value3", "subkey4": "value4", "subkey5": "value5", "subkey6": "value6"}, "key3": {"subkey5": "value5", "subkey6": "value6"}, "key4": {"subkey7": "value7", "subkey8": "value8", "subkey4": "value4", "subkey5": "value4"}}'

# 주어진 규칙에 따라 JSON 문자열을 파싱
parsed_json = parse_json_with_rules(json_string)

# 결과 출력
print(parsed_json)
  • 여기서 object_pairs_hook 옵션은 아래 규칙을 따른다.
    • object_pairs_hook is an optional function that will be called with the result of any object literal decoded with an ordered list of pairs. The return value of object_pairs_hook will be used instead of the dict. This feature can be used to implement custom decoders. If object_hook is also defined, the object_pairs_hook takes priority.

 

 

출력 결과는 아래와 같다.

{
    "key1": {
        "subkey1": "value1",
        "subkey2": "value2",
        "...": "...",
        "subkey4": "value4"
    },
    "key2": {
        "subkey3": "value3",
        "subkey4": "value4",
        "...": "...",
        "subkey6": "value6"
    },
    "...": "...",
    "key4": {
        "subkey7": "value7",
        "subkey8": "value8",
        "...": "...",
        "subkey5": "value4"
    }
}

 

 

위 함수를 통해 API가 재실행될 때 마다 모든 API의 예시 데이터 json 파일을 초기화하는 작업을 추가하였다.

우리 회사의 경우 매일 정각마다 API가 재실행되기에 예시 결과가 적어도 정각까지의 결과라고 보장할 수 있다.

 

Reference

반응형