JSON Formatter Python — คู่มือ json.dumps()
ใช้ จัดรูปแบบและตกแต่ง JSON ฟรีโดยตรงในเบราว์เซอร์ของคุณ — ไม่ต้องติดตั้ง
ลอง จัดรูปแบบและตกแต่ง JSON ออนไลน์ →เมื่อฉันกำลัง debug Python API client สิ่งแรกที่ฉันนึกถึงคือ python pretty print json — เพียงหนึ่งครั้งที่เรียก json.dumps(data, indent=4) ก็เปลี่ยน blob ที่อ่านไม่ออกเป็น string ที่นำทางได้ทันที module json ที่มีในตัวของ Python จัดการเรื่องนี้ทั้งหมดใน standard library — ไม่ต้องติดตั้ง third-party ถ้าต้องการผลลัพธ์รวดเร็วโดยไม่ต้องเขียนโค้ด JSON Formatter ของ ToolDeck ทำได้ทันที คู่มือนี้ครอบคลุมทุกวิธีในทางปฏิบัติ: json.dumps() พร้อมพารามิเตอร์ทั้งหมด, pprint, orjson สำหรับการจัดรูปแบบที่มีประสิทธิภาพสูง, CLI json.tool, และสถานการณ์จริงเช่นการจัดรูปแบบ API response และการอ่านจากดิสก์ — ทั้งหมดด้วย code ที่รองรับ Python 3.8+ รวมถึงการ serialize ประเภทกำหนดเองเช่น datetime และ UUID, การ stream ไฟล์ขนาด gigabyte ด้วย ijson, และการไฮไลต์ syntax บน terminal ด้วย rich.
- →
json.dumps(data, indent=4)มีใน stdlib ของ Python ตั้งแต่เวอร์ชัน 2.6 — ไม่ต้องติดตั้ง - →ส่งผ่าน
ensure_ascii=Falseทุกครั้งที่ข้อมูลมีตัวอักษรที่มีสำเนียง อักขระ CJK หรือ emoji - →สำหรับ
datetime,UUIDหรือ class กำหนดเอง ใช้พารามิเตอร์default=หรือสืบทอดjson.JSONEncoder - →
separators=(',', ':')ลบช่องว่างทั้งหมด — ใช้สำหรับส่งข้อมูลผ่านเครือข่ายหรือฝังใน URL - →
orjsonเร็วกว่า stdlib 5–10× และรองรับdatetimeและuuid.UUIDแบบ native - →
pprint.pprint()ส่งออก Python syntax (True/None) ไม่ใช่ JSON ที่ถูกต้อง — ไม่ควรใช้สำหรับไฟล์หรือ API response - →สำหรับไฟล์ JSON ที่ใหญ่กว่า 50 MB ให้ stream ด้วย
ijsonแทนjson.load()เพื่อหลีกเลี่ยงMemoryError
JSON Pretty Printing คืออะไร?
Pretty printing แปลง JSON string ที่แน่นและย่อขนาดให้เป็นรูปแบบที่อ่านง่าย ด้วยการย่อหน้าและขึ้นบรรทัดใหม่ที่สม่ำเสมอ การแปลงนี้เป็นเพียงการแสดงผล: ข้อมูลเหมือนกันทุกอย่าง มีเพียงการนำเสนอที่เปลี่ยนไป module json ของ Python จัดการเรื่องนี้ทั้งหมดใน standard library — ไม่ต้องติดตั้งเพิ่ม
{"id":"usr_9f3a2b","name":"สมชาย ใจดี","roles":["admin","editor"],"prefs":{"theme":"dark","lang":"th"}}{
"id": "usr_9f3a2b",
"name": "สมชาย ใจดี",
"roles": [
"admin",
"editor"
],
"prefs": {
"theme": "dark",
"lang": "th"
}
}json.dumps() — วิธีมาตรฐานในการจัดรูปแบบ JSON
json.dumps() เป็นส่วนหนึ่งของ standard library ของ Python ตั้งแต่ Python 2.6 — เพียง import json, ไม่ต้องติดตั้งเพิ่ม มัน serialize Python object ที่รองรับ JSON เป็น string ที่จัดรูปแบบแล้ว พารามิเตอร์หลักคือ indent: ตั้งค่าเป็น 4 (หรือ 2) เพื่อให้อ่านง่าย
import json
phuchai = {
"id": "usr_9f3a2b",
"name": "สมชาย ใจดี",
"roles": ["admin", "editor"],
"prefs": {"theme": "dark", "lang": "th"}
}
print(json.dumps(phuchai, indent=4, ensure_ascii=False))
# ผลลัพธ์:
# {
# "id": "usr_9f3a2b",
# "name": "สมชาย ใจดี",
# "roles": [
# "admin",
# "editor"
# ],
# "prefs": {
# "theme": "dark",
# "lang": "th"
# }
# }สำหรับการใช้งาน production มักต้องการ sort_keys=True (ผลลัพธ์สม่ำเสมอข้ามการรัน) และ ensure_ascii=False (เก็บอักขระภาษาไทย):
import json
api_response = {
"timestamp": "2024-05-01T10:30:00Z",
"status": "success",
"data": {
"user_id": "usr_9f3a2b",
"display_name": "สุดา มีสุข",
"city": "กรุงเทพ",
"score": 4892.5,
"tags": ["python", "backend", "api"]
}
}
print(json.dumps(api_response, indent=4, sort_keys=True, ensure_ascii=False))
# ผลลัพธ์ (คีย์เรียงแล้ว เก็บภาษาไทย):
# {
# "data": {
# "city": "กรุงเทพ",
# "display_name": "สุดา มีสุข",
# "score": 4892.5,
# "tags": ["api", "backend", "python"],
# "user_id": "usr_9f3a2b"
# },
# "status": "success",
# "timestamp": "2024-05-01T10:30:00Z"
# }json.dumps() คืนค่า string สำหรับการเขียน JSON ที่จัดรูปแบบลง file โดยตรง ใช้ json.dump(data, f, indent=4) (ไม่มี s) — มันเขียนลง file object และหลีกเลี่ยง การสร้าง string ตัวกลางในหน่วยความจำตารางอ้างอิงพารามิเตอร์ json.dumps()
พารามิเตอร์ทั้งหมดเป็นตัวเลือกยกเว้น object เอง ค่าเริ่มต้นสร้าง JSON ที่กระชับและปลอดภัยสำหรับ ASCII — ส่งพารามิเตอร์อย่างชัดเจนสำหรับผลลัพธ์ที่อ่านง่าย
ผลลัพธ์ JSON แบบกระชับด้วยพารามิเตอร์ separators
โดยค่าเริ่มต้น json.dumps() แยกรายการด้วย ", " และคีย์จากค่าด้วย ": ". พารามิเตอร์ separators แทนที่ทั้งคู่ การส่งผ่าน (',', ':') ลบช่องว่างทั้งหมดเพื่อสร้าง JSON ที่ถูกต้องและกระชับที่สุด — มีประโยชน์สำหรับ การส่งผ่านเครือข่าย การฝังใน URL หรือการเก็บ JSON ใน database column ที่ทุก byte มีความสำคัญ
import json
payload = {
"endpoint": "/api/v2/events",
"filters": {"status": "active", "limit": 100},
"sort": "desc"
}
# ค่าเริ่มต้น — มีช่องว่างหลัง separator (อ่านง่าย)
default_out = json.dumps(payload)
# {"endpoint": "/api/v2/events", "filters": {"status": "active", "limit": 100}, "sort": "desc"}
# len = 88
# กระชับ — ไม่มีช่องว่างเลย
compact_out = json.dumps(payload, separators=(',', ':'))
# {"endpoint":"/api/v2/events","filters":{"status":"active","limit":100},"sort":"desc"}
# len = 80 (เล็กลง 9%; ประโยชน์เพิ่มขึ้นกับ payload ที่ซ้อนกันลึก)
# กระชับ + เรียงคีย์สำหรับ cache key หรือ content hash
canonical = json.dumps(payload, separators=(',', ':'), sort_keys=True)
print(canonical)
# {"endpoint":"/api/v2/events","filters":{"limit":100,"status":"active"},"sort":"desc"}indent= พร้อมกับ separators=, อาร์กิวเมนต์ separators ควบคุมเฉพาะ separator inline — การขึ้นบรรทัดใหม่และการย่อหน้าจาก indent ยังคงอยู่ หากต้องการผลลัพธ์บรรทัดเดียวแบบกระชับ ให้ละ indent (หรือส่งผ่าน None) และตั้งค่า separators=(',', ':').การ Serialize Python Object กำหนดเองด้วยพารามิเตอร์ default
module json มาตรฐาน serialize dict, list, string, ตัวเลข, boolean และ None — แต่ raiseTypeError สำหรับประเภทอื่น สาเหตุที่พบบ่อยที่สุดสองอย่างใน production code คือ object datetime และ UUID
import json
from datetime import datetime, timezone
import uuid
order = {
"order_id": uuid.uuid4(), # ❌ TypeError: UUID is not JSON serializable
"placed_at": datetime.now(timezone.utc), # ❌ TypeError: datetime is not JSON serializable
"total_thb": 4500.00,
"items": ["pro-subscription", "addon-storage"]
}
json.dumps(order) # raise TypeErrorวิธีที่ 1 — พารามิเตอร์ default=
ส่งผ่าน callable ไปยัง default= json.dumps() จะเรียก มันสำหรับ object ใดก็ตามที่ไม่สามารถจัดการได้ คืนค่า representation ที่ serialize ได้ หรือ raise TypeError สำหรับประเภทที่ไม่รองรับ — อย่าเงียบกับประเภทที่ไม่รู้จัก
import json
from datetime import datetime, timezone, date
import uuid
from decimal import Decimal
def json_default(obj):
if isinstance(obj, (datetime, date)):
return obj.isoformat()
if isinstance(obj, uuid.UUID):
return str(obj)
if isinstance(obj, Decimal):
return float(obj)
raise TypeError(f"ประเภท {type(obj).__name__!r} ไม่สามารถ serialize เป็น JSON ได้")
order = {
"order_id": uuid.uuid4(),
"placed_at": datetime(2024, 5, 1, 10, 30, 0, tzinfo=timezone.utc),
"total_thb": Decimal("4500.00"),
"items": ["pro-subscription", "addon-storage"]
}
print(json.dumps(order, indent=4, default=json_default))
# {
# "order_id": "a3f1c2d4-e5b6-7890-abcd-ef1234567890",
# "placed_at": "2024-05-01T10:30:00+00:00",
# "total_thb": 4500.0,
# "items": ["pro-subscription", "addon-storage"]
# }วิธีที่ 2 — สืบทอด json.JSONEncoder
สำหรับ encoding logic ที่ใช้ซ้ำได้และแชร์ข้าม module หลายตัว การสืบทอด json.JSONEncoder สะอาดกว่าการส่งฟังก์ชัน default ไปทุกที่ Override method default และเรียก super().default(obj) เป็น fallback สุดท้าย — นี้รักษาพฤติกรรม error ที่ถูกต้องสำหรับประเภทที่ไม่รองรับ
import json
from datetime import datetime, timezone
import uuid
from decimal import Decimal
class AppEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
if isinstance(obj, uuid.UUID):
return str(obj)
if isinstance(obj, Decimal):
return float(obj)
return super().default(obj) # raise TypeError สำหรับประเภทที่ไม่รู้จัก
order = {
"order_id": uuid.uuid4(),
"placed_at": datetime(2024, 5, 1, 10, 30, 0, tzinfo=timezone.utc),
"total_thb": Decimal("4500.00"),
}
# ส่ง encoder class ผ่าน cls=
print(json.dumps(order, indent=4, cls=AppEncoder))
# ผลลัพธ์เหมือนกับวิธี default= ข้างต้นsuper().default(obj) เสมอ (หรือ raise TypeError อย่างชัดเจน) สำหรับประเภทที่ไม่รู้จัก การคืนค่า str(obj) อย่างเงียบสำหรับทุกอย่างจะ ทำให้ object ที่ควร raise error เสียหาย — bug ที่ยากจะติดตามใน productionการถอดรหัสกลับ — object_hook
การ encode เป็นเพียงครึ่งเรื่อง เพื่อสร้าง Python object กำหนดเองจาก JSON ใหม่ ส่งฟังก์ชัน object_hook ไปยัง json.loads() หรือ json.load()hook จะถูกเรียกสำหรับทุก JSON object (dict) ที่ถอดรหัสและสามารถคืนค่า Python ใดก็ได้ แทน — ให้วงจร encode ↔ decode ที่สมบูรณ์
import json
from datetime import datetime
from dataclasses import dataclass
@dataclass
class Event:
name: str
occurred_at: datetime
user_id: str
def encode_event(obj):
if isinstance(obj, Event):
return {
"__type__": "Event",
"name": obj.name,
"occurred_at": obj.occurred_at.isoformat(),
"user_id": obj.user_id,
}
raise TypeError(f"ไม่สามารถ serialize {type(obj)}")
def decode_event(d):
if d.get("__type__") == "Event":
return Event(
name=d["name"],
occurred_at=datetime.fromisoformat(d["occurred_at"]),
user_id=d["user_id"],
)
return d
# Encode
event = Event("login", datetime(2024, 5, 1, 10, 30), "usr_9f3a2b")
json_str = json.dumps(event, default=encode_event, indent=4)
# ถอดรหัสกลับเป็น Event instance
restored = json.loads(json_str, object_hook=decode_event)
print(type(restored)) # <class 'Event'>
print(restored.occurred_at) # 2024-05-01 10:30:00object_hook ถูกเรียกสำหรับทุก dict ที่ซ้อนกันใน document — ไม่ใช่แค่ระดับบนสุด รวม discriminator field (เช่น "__type__") เพื่อให้ hook แยกแยะ object กำหนดเองของคุณจาก dict ธรรมดาที่ควรปล่อยไว้ตามเดิมpprint — Module ทางเลือก (และเมื่อไหรที่ไม่ควรใช้)
module pprint ของ Python (pretty printer) จัดรูปแบบโครงสร้างข้อมูล Python เพื่อให้อ่านง่ายใน terminal มันทำงานกับ Python object ที่ parse แล้ว ไม่ใช่ JSON string — และผลลัพธ์ ใช้ Python syntax ไม่ใช่ JSON syntax
import json, pprint
raw = '{"sensor_id":"s-441","readings":[23.1,23.4,22.9],"unit":"celsius","active":true}'
data = json.loads(raw)
# pprint — Python repr ที่ถูกต้อง ไม่ใช่ JSON ที่ถูกต้อง
pprint.pprint(data, sort_dicts=False)
# {'sensor_id': 's-441',
# 'readings': [23.1, 23.4, 22.9],
# 'unit': 'celsius',
# 'active': True} ← Python True ไม่ใช่ JSON true
# json.dumps — JSON ที่ถูกต้อง
print(json.dumps(data, indent=4))
# {
# "sensor_id": "s-441",
# "readings": [23.1, 23.4, 22.9],
# "unit": "celsius",
# "active": true ← JSON ที่ถูกต้อง
# }pprint ไปยัง API endpoint หรือ เขียนลงไฟล์ .json เด็ดขาด — จะทำลาย JSON parser ใดก็ตามที่คาดหวัง standard syntax ใช้ json.dumps(indent=4) สำหรับผลลัพธ์ทั้งหมด ที่ต้องเป็น JSON ที่ถูกต้องเมื่อ pprint มีประโยชน์: การตรวจสอบ Python object อย่างรวดเร็วใน REPL หรือ debug log โดยเฉพาะเมื่อ object มีประเภทที่ไม่ serialize เป็น JSON ได้ (set, custom class instance, dataclass ก่อนการแปลง)
วิธีพิมพ์ JSON Response จาก Requests ให้สวยงาม
สถานการณ์จริงที่พบบ่อยที่สุด: คุณมีไฟล์ JSON บนดิสก์หรือ HTTP response จาก API และต้องการจัดรูปแบบเพื่อ debug หรือ logging ทั้งสองกรณี ใช้วิธีเดียวกัน — parse เป็น Python dict แล้วจัดรูปแบบด้วย json.dumps()
อ่านจากไฟล์
import json
try:
with open("config.json", "r", encoding="utf-8") as f:
data = json.load(f)
# พิมพ์ให้สวยงามบน console
print(json.dumps(data, indent=4, ensure_ascii=False))
# หรือเขียนเวอร์ชันที่จัดรูปแบบแล้วกลับลงดิสก์
with open("config.pretty.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
except json.JSONDecodeError as e:
print(f"JSON ไม่ถูกต้อง: {e}")
except FileNotFoundError:
print(f"ไม่พบไฟล์: config.json")การจัดรูปแบบ API response
import json, requests
from requests.exceptions import HTTPError, ConnectionError, Timeout
def pretty_print_api(url: str) -> None:
try:
resp = requests.get(url, timeout=10)
resp.raise_for_status()
print(json.dumps(resp.json(), indent=4, ensure_ascii=False))
except HTTPError as e:
print(f"HTTP {e.response.status_code}: {e}")
except (ConnectionError, Timeout) as e:
print(f"Network error: {e}")
except json.JSONDecodeError:
print(f"Response body ไม่ใช่ JSON:\n{resp.text[:500]}")
pretty_print_api("https://api.github.com/repos/python/cpython")response.json() parse response body แล้ว — ไม่จำเป็นต้องเรียก json.loads() แยกต่างหาก เพิ่ม raise_for_status() เสมอก่อนเข้าถึง .json() เพื่อจับ error 4xx/5xx ก่อนที่จะเกิด parse error ที่น่าสับสนการพิมพ์ให้สวยงามจาก Command Line
Python มาพร้อมกับ json.tool, CLI module สำหรับจัดรูปแบบ JSON จาก terminal โดยตรง — ไม่ต้องเขียน Python script ใช้ได้บนเครื่องใดก็ตามที่ติดตั้ง Python
# จัดรูปแบบไฟล์ local
python -m json.tool config.json
# Pipe API response ผ่าน formatter
curl -s https://api.github.com/users/gvanrossum | python -m json.tool
# จัดรูปแบบจาก stdin
echo '{"service":"api-gateway","version":"2.1.0","healthy":true}' | python -m json.tool
# เรียงคีย์ตามตัวอักษร
python -m json.tool --sort-keys data.json
# กำหนด indent เอง (Python 3.9+)
python -m json.tool --indent 2 data.json--indent และ --no-indent สำหรับการกรอง JSON บน terminal ที่มีประสิทธิภาพมากขึ้น พิจารณา jq — แต่ python -m json.tool ครอบคลุมการจัดรูปแบบ โดยไม่มี dependency เพิ่มเติมถ้าคุณไม่ได้อยู่ใน terminal เลย — วางการตอบกลับจาก Postman หรือไฟล์ log — JSON Formatter ของ ToolDeck ช่วยให้วาง จัดรูปแบบ และคัดลอกในขั้นตอนเดียว พร้อม syntax highlighting และการตรวจสอบที่ฝังอยู่
ไลบรารีทางเลือก: orjson และ rich
orjson — เร็วกว่า 5–10× พร้อมรองรับประเภท Native
module json มาตรฐานเร็วพอสำหรับส่วนใหญ่ แต่หาก serialize หลายพันออบเจกต์ต่อวินาที — logging pipeline, API throughput สูง, การส่งออกข้อมูลขนาดใหญ่ — orjson เร็วกว่า 5–10× มันรองรับประเภทที่ standard library ไม่สามารถ serialize ได้โดยไม่ต้องมีฟังก์ชัน default กำหนดเอง: datetime, uuid.UUID, numpy array และ dataclass
pip install orjson
import orjson
from datetime import datetime, timezone
import uuid
event = {
"event_id": uuid.uuid4(), # ไม่ต้อง str() — orjson จัดการ UUID
"timestamp": datetime.now(timezone.utc), # ไม่ต้อง isoformat()
"service": "auth-service",
"level": "INFO",
"payload": {
"user_id": "usr_9f3a2b",
"action": "login",
"ip": "192.168.1.42",
"latency_ms": 34
}
}
# orjson.dumps คืนค่า bytes; .decode() แปลงเป็น str
print(orjson.dumps(event, option=orjson.OPT_INDENT_2).decode())
# {
# "event_id": "a3f1c2d4-e5b6-7890-abcd-ef1234567890",
# "timestamp": "2024-05-01T10:30:00+00:00",
# "service": "auth-service",
# ...
# }สองสิ่งที่ควรรู้: orjson.dumps() คืนค่า bytes, ไม่ใช่ string — เรียก .decode() หากต้องการ string รองรับเฉพาะ 2-space indent ผ่าน OPT_INDENT_2; สำหรับผลลัพธ์ 4-space ใช้ json.dumps(indent=4) มาตรฐาน
rich — การไฮไลต์ Syntax บน Terminal
หากตรวจสอบ JSON บน terminal หรือ REPL เป็นประจำ rich แสดงผลแบบมีสีและไฮไลต์ syntax ที่ทำให้โครงสร้างที่ซ้อนกันลึกอ่านง่ายทันที คีย์ string ตัวเลข และ boolean แต่ละอย่างมีสีเฉพาะ — ง่ายกว่าการมองข้อความ monochrome มาก เป็นเครื่องมือ debug เท่านั้น ไม่ใช่สำหรับ production serialization
pip install rich
from rich import print_json
import json
# print_json() รับ JSON string
raw = '{"event":"login","user_id":"usr_9f3a2b","timestamp":"2024-05-01T10:30:00Z","success":true,"meta":{"ip":"192.168.1.42","attempts":1}}'
print_json(raw)
# สำหรับการพิมพ์ Python dict ให้สวยงาม แปลงเป็น string ก่อน
data = {
"status": "success",
"count": 42,
"tags": ["python", "api", "backend"]
}
print_json(json.dumps(data))rich.print_json() ส่งออก ANSI escape codes สำหรับสี terminal — ห้ามนำผลลัพธ์นี้ไปเขียนลงไฟล์ .json หรือส่งเป็น API response เด็ดขาด ใช้ json.dumps(indent=4) สำหรับ ผลลัพธ์ที่เครื่องต้องอ่านได้simplejson — การแทนที่แบบ Drop-in ที่รองรับ stdlib
simplejson คือไลบรารีที่กลายเป็น module json มาตรฐานของ Python — ยังคงได้รับการดูแลอย่างอิสระและนำหน้า stdlib ในฟีเจอร์เล็กน้อย เป็น drop-in replacement จริงๆ: เปลี่ยน import และ code ที่เหลือไม่เปลี่ยน มีประโยชน์เมื่อต้องการรองรับ Decimal โดยไม่ต้องใช้ encoder กำหนดเอง หรือเมื่อต้องการรองรับ Python เวอร์ชันเก่า
pip install simplejson
import simplejson as json # API เหมือนกับ stdlib
from decimal import Decimal
order = {
"item": "API subscription",
"price": Decimal("149.99"), # stdlib json raise TypeError ที่นี่
"quantity": 3,
}
# simplejson serialize Decimal แบบ native — ไม่ต้องใช้ default=
print(json.dumps(order, indent=4, use_decimal=True))
# {
# "item": "API subscription",
# "price": 149.99,
# "quantity": 3
# }orjson เป็นตัวเลือกที่ดีกว่า ใช้ simplejson เมื่อต้องการ serialize Decimal แบบ native โดยไม่เขียน encoder กำหนดเอง หรือเมื่อดูแล codebase ที่ใช้อยู่แล้วการประมวลผลไฟล์ JSON ขนาดใหญ่โดยไม่ใช้หน่วยความจำหมด
json.load() อ่านไฟล์ทั้งหมดเข้าหน่วยความจำก่อนที่คุณจะเข้าถึงฟิลด์เดียวได้ สำหรับไฟล์ ที่มีบันทึกหลายล้านรายการหรือ payload ที่เกินหนึ่งกิกะไบต์ จะทำให้เกิด MemoryError — หรืออย่างดีที่สุดบังคับให้ process ใช้ swap และทำงานช้า
Streaming ด้วย ijson
ijson คือ streaming JSON parser ที่สร้าง item ทีละรายการจาก file object คุณวนซ้ำผ่าน array element โดยไม่เก็บ dataset ทั้งหมดในหน่วยความจำ — หน่วยความจำสูงสุดเป็นสัดส่วนกับ object เดียว ไม่ใช่ขนาดไฟล์
pip install ijson
import ijson
from decimal import Decimal
# events.json โครงสร้าง: {"events": [...หลายล้าน object...]}
total_revenue = Decimal("0")
login_count = 0
with open("events.json", "rb") as f: # ijson ต้องการ binary mode
for event in ijson.items(f, "events.item"):
if event.get("type") == "purchase":
total_revenue += Decimal(str(event["amount_thb"]))
elif event.get("type") == "login":
login_count += 1
print(f"รายได้: {total_revenue:,.2f} THB | Logins: {login_count}")
# ประมวลผลไฟล์ 2 GB ด้วยหน่วยความจำสูงสุด ~30 MBjson.load() เป็น ijson เมื่อไฟล์เกินประมาณ 50–100 MB ต่ำกว่านั้น json.load() ง่ายกว่า และเร็วกว่ามากเพราะใช้ C-extension parser ภายใน เกิน 100 MB ประโยชน์การประหยัดหน่วยความจำจาก streaming มีน้ำหนักเกินค่าใช้จ่ายเพิ่มเติมNDJSON — หนึ่ง JSON object ต่อบรรทัด
NDJSON (Newline Delimited JSON หรือที่เรียกว่า JSON Lines หรือ .jsonl) เก็บ JSON object ที่สมบูรณ์หนึ่งรายการต่อบรรทัด Log exporter, Kafka consumer และ data pipeline มักสร้างรูปแบบนี้เพราะแต่ละบรรทัดสามารถ append และอ่านได้อย่างอิสระ — ไม่ต้อง parse ทั้งไฟล์เพื่อเพิ่มบันทึก standard library จัดการได้โดยไม่มี dependency เพิ่ม
import json
from pathlib import Path
# เขียน NDJSON — หนึ่ง event ต่อบรรทัด
events = [
{"ts": "2024-05-01T10:00:00Z", "user": "usr_9f3a2b", "action": "login"},
{"ts": "2024-05-01T10:01:03Z", "user": "usr_9f3a2b", "action": "purchase", "sku": "pro-plan"},
{"ts": "2024-05-01T10:15:42Z", "user": "usr_4ab1d9", "action": "login"},
]
with open("events.ndjson", "w", encoding="utf-8") as f:
for event in events:
f.write(json.dumps(event, ensure_ascii=False) + "\n")
# อ่าน NDJSON — หน่วยความจำคงที่ ไม่ว่าไฟล์จะใหญ่แค่ไหน
purchase_count = 0
with open("events.ndjson", "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line: # ข้ามบรรทัดว่าง
continue
event = json.loads(line)
if event.get("action") == "purchase":
purchase_count += 1
print(f"{event['ts']} — {event['user']} ซื้อ {event['sku']}")ข้อผิดพลาดที่พบบ่อย
ฉันเห็นข้อผิดพลาดสี่ข้อนี้ในเกือบทุก code review ที่เกี่ยวข้องกับ JSON serialization — โดยเฉพาะจาก developer ที่มาจาก JavaScript ที่ JSON.stringify จัดการ encoding โดยอัตโนมัติ
ปัญหา: print() บน dict ใช้ Python repr — ผลลัพธ์แสดง True/None (Python syntax) ไม่ใช่ true/null (JSON syntax) ไม่ใช่ JSON ที่ถูกต้อง
วิธีแก้: ใช้ json.dumps(data, indent=4) เสมอสำหรับผลลัพธ์ JSON ที่ถูกต้องและอ่านง่าย
data = {"active": True, "count": None}
print(data)
# {'active': True, 'count': None}print(json.dumps(data, indent=4))
# {
# "active": true,
# "count": null
# }ปัญหา: อักขระพิเศษ (ตัวอักษรภาษาไทย, emoji) ถูก escape เป็นลำดับ \\uXXXX ทำให้ผลลัพธ์อ่านไม่ออก
วิธีแก้: ส่งผ่าน ensure_ascii=False เพื่อเก็บอักขระ Unicode ดั้งเดิม
user = {"name": "สมชาย ใจดี", "city": "กรุงเทพ"}
json.dumps(user, indent=2)
# {"name": "\u0e2a\u0e21\u0e0a\u0e32\u0e22...", "city": "\u0e01\u0e23\u0e38..."}json.dumps(user, indent=2, ensure_ascii=False)
# {"name": "สมชาย ใจดี", "city": "กรุงเทพ"}ปัญหา: json.dumps() คืนค่า string; จากนั้นต้องเรียก f.write() แยกต่างหาก สร้าง string ตัวกลางที่ไม่จำเป็น
วิธีแก้: ใช้ json.dump(data, f, indent=4) — เขียนลง file object โดยตรง
with open("out.json", "w") as f:
f.write(json.dumps(data, indent=4))with open("out.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)ปัญหา: pprint.pprint() ใช้ Python syntax (True, None, single quotes) ที่ JSON parser ปฏิเสธ
วิธีแก้: ใช้ json.dumps(indent=4) สำหรับผลลัพธ์ใดก็ตามที่ต้อง parse เป็น JSON ได้
import pprint
pprint.pprint({"running": True, "last_error": None})
# {'running': True, 'last_error': None}import json
print(json.dumps({"running": True, "last_error": None}, indent=4))
# {"running": true, "last_error": null}การเปรียบเทียบวิธีการ — json.dumps, orjson, simplejson, rich
ใช้ json.dumps() สำหรับการจัดรูปแบบประจำวันและการเขียนไฟล์ — ครอบคลุม 95% ของ use case โดยไม่มี dependency เลือกใช้ orjson เมื่อ serialize ใน hot path หรือเมื่อ object มีฟิลด์ datetime และ UUIDใช้ simplejson เมื่อต้องการ drop-in ที่รองรับ stdlib พร้อม Decimal สำเร็จรูป จำกัดการใช้ rich.print_json() และ pprint เฉพาะสำหรับการตรวจสอบ terminal ในพื้นที่ — ทั้งสองไม่สร้างผลลัพธ์ที่เครื่องอ่านได้
คำถามที่พบบ่อย
จะพิมพ์ JSON ให้สวยงามใน Python ได้อย่างไร?
เรียก json.dumps(data, indent=4) พารามิเตอร์ indent กำหนดจำนวนช่องว่างต่อระดับการซ้อน import module json ก่อน — มาพร้อมกับ standard library ของ Python ไม่ต้อง pip install ส่งผ่าน ensure_ascii=False หากข้อมูลมีอักขระ non-ASCII เช่น ตัวอักษรภาษาไทยหรืออักษร CJK
import json
phuchai = {"username": "somchai", "plan": "enterprise", "permissions": ["read", "write", "deploy"]}
print(json.dumps(phuchai, indent=4, ensure_ascii=False))ความแตกต่างระหว่าง json.dumps() และ json.dump() คืออะไร?
json.dumps() (มีตัว "s") คืนค่า string ที่จัดรูปแบบแล้วในหน่วยความจำ json.dump() (ไม่มี "s") เขียนลง file-like object โดยตรง — ส่ง file handle ที่เปิดอยู่เป็นอาร์กิวเมนต์ที่สอง สำหรับการเขียน JSON ที่จัดรูปแบบลงดิสก์ json.dump(data, f, indent=4) เป็นวิธีที่นิยมและหลีกเลี่ยงการสร้าง string ตัวกลาง
# dumps → string ในหน่วยความจำ
formatted = json.dumps(data, indent=4)
# dump → เขียนลง file โดยตรง
with open('output.json', 'w', encoding='utf-8') as f:
json.dump(data, f, indent=4)ทำไม json.dumps() แสดง \u0e2a\u0e27\u0e31 แทนที่จะเป็นตัวอักษรจริง?
โดยค่าเริ่มต้น ensure_ascii=True จะ escape อักขระ non-ASCII ทุกตัวเป็นลำดับ \uXXXX ตั้งค่า ensure_ascii=False เพื่อเก็บอักขระ Unicode ดั้งเดิม สิ่งนี้สำคัญมากสำหรับชื่อคน ที่อยู่ และเนื้อหาที่ผู้ใช้สร้างขึ้นในภาษาไทยหรือภาษาที่ไม่ใช้ตัวอักษรละติน
data = {"mueang": "กรุงเทพ", "salam": "สวัสดี", "prathet": "ไทย"}
# ค่าเริ่มต้น — ถูก escape
json.dumps(data, indent=4)
# {"mueang": "\u0e01\u0e23\u0e38\u0e07\u0e40\u0e17\u0e1e", ...}
# อ่านได้
json.dumps(data, indent=4, ensure_ascii=False)
# {"mueang": "กรุงเทพ", "salam": "สวัสดี", "prathet": "ไทย"}จะพิมพ์ JSON string (ไม่ใช่ dict) ให้สวยงามได้อย่างไร?
ก่อนอื่น parse string ด้วย json.loads() แล้วจัดรูปแบบด้วย json.dumps() การเรียกสองครั้งสามารถเชื่อมต่อกันในบรรทัดเดียวสำหรับการตรวจสอบบน terminal อย่างรวดเร็ว
import json
raw = '{"endpoint":"/api/v2/users","timeout":30,"retry":true}'
print(json.dumps(json.loads(raw), indent=4))ใช้ pprint จัดรูปแบบ JSON ใน Python ได้ไหม?
pprint.pprint() สร้าง Python object representation ไม่ใช่ JSON ที่ถูกต้อง ใช้ True/False/None (Python syntax) แทน true/false/null (JSON syntax) อย่าส่ง pprint output ไปยัง API หรือ JSON parser เด็ดขาด — ใช้ json.dumps(indent=4) สำหรับทุกสิ่งที่ต้องเป็น JSON ที่ถูกต้อง
import pprint, json
data = {"active": True, "score": None}
pprint.pprint(data) # {'active': True, 'score': None} ← ไม่ใช่ JSON
json.dumps(data, indent=4) # {"active": true, "score": null} ← JSON ถูกต้องจะเรียงคีย์ JSON ตามตัวอักษรใน Python ได้อย่างไร?
เพิ่ม sort_keys=True ใน json.dumps() สำหรับ command line ใช้ python -m json.tool --sort-keys data.json คีย์ที่เรียงแล้วทำให้ JSON diff อ่านง่ายและช่วยระบุค่าที่เปลี่ยนแปลงได้รวดเร็ว
import json
server = {"workers": 4, "host": "0.0.0.0", "port": 8080, "debug": False}
print(json.dumps(server, indent=4, sort_keys=True))
# {
# "debug": false,
# "host": "0.0.0.0",
# "port": 8080,
# "workers": 4
# }Python ให้การควบคุมเต็มรูปแบบ — custom serializers, streaming, การรวม pipeline เมื่อต้องการตรวจสอบหรือแชร์ snippet ที่จัดรูปแบบแล้ว JSON Formatter ของ ToolDeck คือเส้นทางที่เร็วกว่า: วาง JSON แล้วรับผลลัพธ์ที่เยื้องและไฮไลต์โดยไม่ต้องตั้งค่าสภาพแวดล้อม
เครื่องมือที่เกี่ยวข้อง
Maria is a backend developer specialising in Python and API integration. She has broad experience with data pipelines, serialisation formats, and building reliable server-side services. She is an active member of the Python community and enjoys writing practical, example-driven guides that help developers solve real problems without unnecessary theory.
Dmitri is a DevOps engineer who relies on Python as his primary scripting and automation language. He builds internal tooling, CI/CD pipelines, and infrastructure automation scripts that run in production across distributed teams. He writes about the Python standard library, subprocess management, file processing, encoding utilities, and the practical shell-adjacent Python that DevOps engineers use every day.