Đang tải và phân tích cú pháp tệp JSON với nhiều đối tượng JSON


101

Tôi đang cố gắng tải và phân tích cú pháp tệp JSON bằng Python . Nhưng tôi gặp khó khăn khi cố gắng tải tệp:

import json
json_data = open('file')
data = json.load(json_data)

Sản lượng:

ValueError: Extra data: line 2 column 1 - line 225116 column 1 (char 232 - 160128774)

Tôi nhìn vào 18,2. json- Bộ mã hóa và giải mã JSON trong tài liệu Python, nhưng thật không khuyến khích khi đọc qua tài liệu trông kinh khủng này.

Một vài dòng đầu tiên (ẩn danh với các mục nhập ngẫu nhiên):

{"votes": {"funny": 2, "useful": 5, "cool": 1}, "user_id": "harveydennis", "name": "Jasmine Graham", "url": "http://example.org/user_details?userid=harveydennis", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 1, "useful": 2, "cool": 4}, "user_id": "njohnson", "name": "Zachary Ballard", "url": "https://www.example.com/user_details?userid=njohnson", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 1, "useful": 0, "cool": 4}, "user_id": "david06", "name": "Jonathan George", "url": "https://example.com/user_details?userid=david06", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 6, "useful": 5, "cool": 0}, "user_id": "santiagoerika", "name": "Amanda Taylor", "url": "https://www.example.com/user_details?userid=santiagoerika", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 1, "useful": 8, "cool": 2}, "user_id": "rodriguezdennis", "name": "Jennifer Roach", "url": "http://www.example.com/user_details?userid=rodriguezdennis", "average_stars": 3.5, "review_count": 12, "type": "user"}

Câu trả lời:


222

Bạn có tệp văn bản định dạng JSON Lines . Bạn cần phân tích cú pháp tệp của mình theo từng dòng:

import json

data = []
with open('file') as f:
    for line in f:
        data.append(json.loads(line))

Mỗi dòng chứa JSON hợp lệ, nhưng nhìn chung, nó không phải là giá trị JSON hợp lệ vì không có danh sách cấp cao nhất hoặc định nghĩa đối tượng.

Lưu ý rằng vì tệp chứa JSON trên mỗi dòng, bạn sẽ đỡ phải đau đầu khi cố gắng phân tích cú pháp tất cả trong một lần hoặc tìm ra trình phân tích cú pháp JSON trực tuyến. Bây giờ bạn có thể chọn xử lý từng dòng riêng biệt trước khi chuyển sang dòng tiếp theo, tiết kiệm bộ nhớ trong quá trình này. Bạn có thể không muốn nối mỗi kết quả vào một danh sách và sau đó xử lý mọi thứ nếu tệp của bạn thực sự lớn.

Nếu bạn có tệp chứa các đối tượng JSON riêng lẻ có dấu phân cách ở giữa, hãy sử dụng Làm cách nào để sử dụng mô-đun 'json' để đọc từng đối tượng JSON? để phân tích cú pháp các đối tượng riêng lẻ bằng phương thức đệm.


2
+1 Có thể cần lưu ý rằng nếu bạn không cần tất cả các đối tượng cùng một lúc, xử lý từng đối tượng một có thể là cách tiếp cận hiệu quả hơn. Bằng cách này, bạn sẽ không cần phải lưu trữ toàn bộ dữ liệu trong bộ nhớ mà chỉ cần một phần nhỏ của nó.
Tadeck

1
@Pi_: bạn sẽ có từ điển, vì vậy chỉ cần truy cập vào các trường dưới dạng khóa:data = json.loads(line); print data[u'votes']
Martijn Pieters

1
@Pi_: in kết quả của json.loads () sau đó hoặc sử dụng trình gỡ lỗi để kiểm tra.
Martijn Pieters

1
@Pi_: không; đừng nhầm giữa định dạng JSON với biểu diễn chính tả python. Bạn đang thấy từ điển python với chuỗi ngay bây giờ.
Martijn Pieters

1
@ user2441441: xem câu trả lời được liên kết từ bài đăng tại đây.
Martijn Pieters


4

Đó là sai định dạng. Bạn có một đối tượng JSON trên mỗi dòng, nhưng chúng không được chứa trong cấu trúc dữ liệu lớn hơn (tức là một mảng). Bạn sẽ cần phải định dạng lại nó để nó bắt đầu bằng [và kết thúc bằng ]dấu phẩy ở cuối mỗi dòng hoặc phân tích cú pháp từng dòng dưới dạng các từ điển riêng biệt.


20
Với một tệp 50MB, OP có lẽ tốt hơn nên xử lý từng dòng dữ liệu. :-)
Martijn Pieters

11
Việc tệp có định dạng sai hay không tùy thuộc vào quan điểm của mỗi người. Nếu nó được dự định ở định dạng "dòng JSON" thì nó hợp lệ. Xem: jsonlines.org
LS
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.