[python] JSON이란?

Hyeseong·2021년 1월 3일
0

python

목록 보기
17/22

JSON?🎈

전형적인 json 형태의 표현이에요.
key-value 형식의 pair입니다.

{
    "firstName": "Jane",
    "lastName": "Doe",
    "hobbies": ["running", "sky diving", "singing"],
    "age": 35,
    "children": [
        {
            "firstName": "Alice",
            "age": 6
        },
        {
            "firstName": "Bob",
            "age": 8
        }
    ]
}

어찌 보면 전형적인 파이썬 dictionary 형태라는 것도 인식 할 수 있어요.


파이썬의 built-in package -> JSON🎇

내장 패키지로 json을 사용할 수 있어요.

import json

용어 정리🎇

JSON형태로 변형 시키는걸 serialization 이라고 하고 그 반대는 deserialization이라고 하겠조?

PythonJSON
dictobject
list, tuplearray
strstring
int, long, floatnumber
Truetrue
Falsefalse
Nonenull

Serialization(encoding) - Case1🎇

메모리에 아래와 저장된 것을 파일로 저장 시켜 볼까요?

data = {
    "president": {
        "name": "Zaphod Beeblebrox",
        "species": "Betelgeusian"
    }
}

context manager를 이용해서 data_file.json이름의 파일을 만들어 볼거에요.

json.dump() 이녀석을 사용해서 첫 번째 인자에 python python dictionary 객체를 넣고 2번째에는 작성할 파일의 변수를 넣어주면 되요.

serialization해야 할 data 를 첫번째 위치인수로 지정하고 bytes로 작성되어야 할 것을 2번째 위치 인수로 지정합니다.

with open('data_file.json', 'w') as wirete_file:
	json.dump(data, write_file)

만약 2번째 인수가 json.dumps(data)에 지정하지 않으면 disk에 저장하는게 아니에요~


기억해 둘 키워드 인자들🎇

  • indent : 말그대로 indentaion을 넣어줘요.
  • separator: 구분자를 설정해줘요.(기본 값으로 콤마(,)와 콜론(:)이 적용되요.
  • sort_keys: True로 설정하면 key를 기준으로 정렬해요.
print('첫 번째 아래 표준형입니다.')
print(json.dumps(data))
print('두 번째 아래 indent=5 넣었을 때')
print(json.dumps(data, indent=5))
print('세 번째 아래 sort_keys=True 했을때')
print(json.dumps(data, indent=5, sort_keys=True))
print('네 번째 아래 separators=(\'!\', \'@\') 넣었어요')
print(json.dumps(data, indent=5, sort_keys=True, separators=('!', '@')))

output
첫 번째 줄은 보기가 어렵지만

3 번째부터는 적당히 인덱트가 넣어져서 일기 매우 좋아요~ 가독성굿~!

첫 번째 아래 표준형입니다.
{"president": {"name": "Zaphod Beeblebrox", "species": "Betelgeusian", "age": 22}}
두 번째 아래 indent=5 넣었을 때
{
     "president": {
          "name": "Zaphod Beeblebrox",
          "species": "Betelgeusian",
          "age": 22
     }
}
세 번째 아래 sort_keys=True 했을때
{
     "president": {
          "age": 22,
          "name": "Zaphod Beeblebrox",
          "species": "Betelgeusian"
     }
}
네 번째 아래 separators=('!', '@') 넣었어요
{
     "president"@{
          "age"@22!
          "name"@"Zaphod Beeblebrox"!
          "species"@"Betelgeusian"
     }
}

Deserializing(decoding)🎇

Case1에서 dump(), dumps()를 통해서 Python 데이터를 JSON 데이터로 변환시키는걸 봤조?

이제는 이와 대응되는 'load()`, 'loads()'메서드를 통해서 JSON --> Python 데이터로 변화시키는걸 볼게요.

JSONPython
objectdict
arraylist
stringstr
number(int) int
number(real) float
trueTrue
falseFalse
nullNone

기본적으로 서로 encoding(serialization), JSON화하기 <-->>decoding(serialization), python 객체화하기 대응된다고 했는데, 실제로는 그렇지도 않습니다.

한번 보시조.

요약하면 처음 파이썬 튜플인코딩 -> 디코딩을 거쳐 당연히 튜플로 나올줄 알았는데
리스트로 나타난걸 확인 할 수 있어요.

이점에 유의하면 되요.

print('인코딩 디코딩 서로 정확히 대응될까요?')
blackjack_hand = (8, "Q")
print(type(blackjack_hand))
encoded_hand = json.dumps(blackjack_hand)
print('인코딩한거',encoded_hand, '데이터유형',type(encoded_hand))
decoded_hand = json.loads(encoded_hand)
print('디코딩한거',decoded_hand, '데이터유형',type(decoded_hand))
print(blackjack_hand == decoded_hand, '이론상 서로 같아야 해요.')

output

인코딩 디코딩 서로 정확히 대응될까요?
<class 'tuple'>
인코딩한거 [8, "Q"] 데이터유형 <class 'str'>
디코딩한거 [8, 'Q'] 데이터유형 <class 'list'>
False 이론상 서로 같아야 해요.
<class 'tuple'> 파이썬 데이터형
<class 'list'> 인코딩하고 나서 파이썬 데이터 유형
True 결국 튜플로 해줘야 동일함

Deserialization(decoding) - Case2🎇

Case1과는 정반대로 disk에 저장된 데이터를 메모리에 올려서 데이터 마사지를 하고 싶다면 어떻게 할까요?

우선 with open() 구문을 read 모드를 이요해서 열여줘야겠조?

with open("data_file.json", "r") as read_file:
    data = json.load(read_file)
json_string = """
{
    "researcher": {
        "name": "Ford Prefect",
        "species": "Betelgeusian",
        "relatives": [
            {
                "name": "Zaphod Beeblebrox",
                "species": "Betelgeusian"
            }
        ]
    }
}
"""
data = json.loads(json_string)

실사례✨

이번에는 requests 모듈을 사용할게요(없으면 pip install requests해주세요)

import json
import requests

response = requests.get("https://jsonplaceholder.typicode.com/todos")
todos = json.loads(response.text)
print()
print()
print('실사례!')
print(todos == response.json())
print(type(todos))
print(todos[:10])

output

실사례!
True
<class 'list'>
[{'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}, {'userId': 1, 'id': 2, 'title': 'quis ut nam facilis et officia qui', 'completed': False}, {'userId': 1, 'id': 3, 'title': 'fugiat veniam minus', 'completed': False}, {'userId': 1, 'id': 4, 'title': 'et porro tempora', 'completed': True}, {'userId': 1, 'id': 5, 'title': 'laboriosam mollitia et enim quasi adipisci quia provident illum', 'completed': False}, {'userId': 1, 'id': 6, 'title': 'qui ullam ratione quibusdam voluptatem quia omnis', 'completed': False}, {'userId': 1, 'id': 7, 'title': 'illo expedita consequatur quia in', 'completed': False}, {'userId': 1, 'id': 8, 'title': 'quo adipisci enim quam ut ab', 'completed': True}, {'userId': 1, 'id': 9, 'title': 'molestiae perspiciatis ipsa', 'completed': False}, {'userId': 1, 'id': 10, 'title': 'illo est ratione doloremque quia maiores aut', 'completed': True}]

아래 코드를 한번 쭉쭉 이해한다? 그럼 JSON을 파이썬 객체와 같이 술술술 작성하는 경지에 이른거에요!
저는 아니지만~ 예~~~!!!

# Map of userId to number of complete TODOs for that user
todos_by_user = {}

# Increment complete TODOs count for each user.
for todo in todos:
    if todo["completed"]:
        try:
            # Increment the existing user's count.
            todos_by_user[todo["userId"]] += 1
        except KeyError:
            # This user has not been seen. Set their count to 1.
            todos_by_user[todo["userId"]] = 1

# Create a sorted list of (userId, num_complete) pairs.
top_users = sorted(todos_by_user.items(), 
                   key=lambda x: x[1], reverse=True)

# Get the maximum number of complete TODOs.
max_complete = top_users[0][1]

# Create a list of all users who have completed
# the maximum number of TODOs.
users = []
for user, num_complete in top_users:
    if num_complete < max_complete:
        break
    users.append(str(user))

max_users = " and ".join(users)

s = "s" if len(users) > 1 else ""
print(f"user{s} {max_users} completed {max_complete} TODOs")
# users 5 and 10 completed 12 TODOs

아래 코드까지 이해했다?! 그럼 당신은 정말이지~~!!!

# Define a function to filter out completed TODOs 
# of users with max completed TODOS.
def keep(todo):
    is_complete = todo["completed"]
    has_max_count = str(todo["userId"]) in users
    return is_complete and has_max_count

# Write filtered TODOs to file.
with open("filtered_data_file.json", "w") as data_file:
    filtered_todos = list(filter(keep, todos))
    json.dump(filtered_todos, data_file, indent=2)
profile
어제보다 오늘 그리고 오늘 보다 내일...

0개의 댓글