Tại sao Python không thể phân tích dữ liệu JSON này?


1439

Tôi có JSON này trong một tệp:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": [
        "id": "valore"
    ],
    "om_points": "value",
    "parameters": [
        "id": "valore"
    ]
}

Tôi đã viết tập lệnh này để in tất cả dữ liệu JSON:

import json
from pprint import pprint

with open('data.json') as f:
    data = json.load(f)

pprint(data)

Chương trình này đưa ra một ngoại lệ, mặc dù:

Traceback (most recent call last):
  File "<pyshell#1>", line 5, in <module>
    data = json.load(f)
  File "/usr/lib/python3.5/json/__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.5/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.5/json/decoder.py", line 355, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 13 column 13 (char 213)

Làm cách nào tôi có thể phân tích cú pháp JSON và trích xuất các giá trị của nó?


@kederrac Vì lý do được đưa ra: "Câu hỏi này được gây ra bởi một lỗi đánh máy hoặc một vấn đề không còn có thể được sao chép." Các json không hợp lệ.
Cướp

@kederrac Vấn đề là do lỗi trong quá trình sử dụng không phải vì nó có thể được sao chép.
Cướp

Câu trả lời:


2128

Dữ liệu của bạn không phải là định dạng JSON hợp lệ . Bạn có []khi bạn nên có {}:

  • []dành cho mảng JSON, được gọi listtrong Python
  • {}dành cho các đối tượng JSON, được gọi dicttrong Python

Đây là cách tệp JSON của bạn sẽ trông như thế nào:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": {
        "id": "valore"
    },
    "om_points": "value",
    "parameters": {
        "id": "valore"
    }
}

Sau đó, bạn có thể sử dụng mã của mình:

import json
from pprint import pprint

with open('data.json') as f:
    data = json.load(f)

pprint(data)

Với dữ liệu, bây giờ bạn cũng có thể tìm thấy các giá trị như vậy:

data["maps"][0]["id"]
data["masks"]["id"]
data["om_points"]

Hãy thử những điều đó và xem nếu nó bắt đầu có ý nghĩa.


1
Ok vì vậy tôi phải kiểm soát mã của mình vì tệp json này được tạo từ một đối tượng java. Cảm ơn.
michele

5
Cảm ơn giải pháp. Tôi đang nhận được một biểu tượng unicode trong khi in nó. (ví dụ: u'valore '). Làm thế nào để ngăn chặn nó?
nhật ký 30/1/2015

6
Đẹp nhưng trăn thêm một u'trước mỗi phím. Bất cứ ý tưởng tại sao?
CodyBugstein

7
Đó là lý do tại sao văn bản của bạn là loại unicode không phải là chuỗi. Hầu hết thời gian sẽ tốt hơn khi có văn bản trong unicode cho tiếng Đức và để chia sẻ kết quả văn bản với các mô-đun / chương trình khác, v.v. Vì vậy, bạn tốt!
Michael P

2
Tôi muốn thực hiện một quan sát hy vọng là hữu ích, và chắc chắn là mỉa mai. Tôi thấy mô-đun pprint kém hơn mô-đun json cho json in ấn đẹp. Nếu bạn thử cả hai, tôi nghĩ bạn sẽ đồng ý. Để hiển thị và gỡ lỗi cấu trúc dữ liệu json của tôi, tôi đã thực hiện: output = json.dumps (data_itectture, indent = 2, sort_keys = True) in (đầu ra) Tôi nghĩ bạn sẽ tìm thấy điều khiển thụt lề, sắp xếp và thông minh line-quấn trong phương thức dumps () là khá theo ý thích của bạn. Nếu suy nghĩ của tôi là sai, xin vui lòng cho tôi biết.
Larold

307

Bạn data.jsonsẽ trông như thế này:

{
 "maps":[
         {"id":"blabla","iscategorical":"0"},
         {"id":"blabla","iscategorical":"0"}
        ],
"masks":
         {"id":"valore"},
"om_points":"value",
"parameters":
         {"id":"valore"}
}

Mã của bạn phải là:

import json
from pprint import pprint

with open('data.json') as data_file:    
    data = json.load(data_file)
pprint(data)

Lưu ý rằng điều này chỉ hoạt động trong Python 2.6 trở lên, vì nó phụ thuộc vào with-statement . Trong Python 2.5 sử dụngfrom __future__ import with_statement , trong Python <= 2.4, hãy xem câu trả lời của Justin Peel , câu trả lời này dựa trên.

Bây giờ bạn cũng có thể truy cập các giá trị đơn như thế này:

data["maps"][0]["id"]  # will return 'blabla'
data["masks"]["id"]    # will return 'valore'
data["om_points"]      # will return 'value'

7
Tôi có một downvote về điều này. Có lẽ nó không rõ ràng, tại sao tôi nghĩ rằng một câu trả lời khác là cần thiết. Đã thêm ghi chú về tính tương thích của câu lệnh with.
Bengt

Xin lỗi vì đã quay lại, nhưng mã được đề xuất sẽ giữ data_file opened lâu hơn mức cần thiết.
Bengt

Tham khảo tài liệu 2.6 ( docs.python.org/2.6/l Library / io.html ), mở tệp trong ngữ cảnh "với" sẽ tự động đóng tệp.
Steve S.

1
@SteveS. Có, nhưng không phải trước khi bối cảnh còn lại. pprinting trong with-context giữ data_filemở lâu hơn.
Bengt

1
@GayanPathirage bạn truy cập vào nó như data["om_points"], data["masks"]["id"]. Ý tưởng là bạn có thể đạt được bất kỳ cấp độ nào trong từ điển bằng cách chỉ định 'đường dẫn chính'. Nếu bạn nhận được một KeyErrorngoại lệ, điều đó có nghĩa là khóa không tồn tại trong đường dẫn. Xem ra lỗi chính tả hoặc kiểm tra cấu trúc từ điển của bạn.
Nuhman

71

Câu trả lời của Justin Peel thực sự hữu ích, nhưng nếu bạn đang sử dụng Python 3 thì đọc JSON nên được thực hiện như sau:

with open('data.json', encoding='utf-8') as data_file:
    data = json.loads(data_file.read())

Lưu ý: sử dụng json.loadsthay vì json.load. Trong Python 3, json.loadslấy tham số chuỗi. json.loadmất một tham số đối tượng giống như tập tin. data_file.read()trả về một đối tượng chuỗi.

Thành thật mà nói, tôi không nghĩ rằng vấn đề là tải tất cả dữ liệu json vào bộ nhớ trong hầu hết các trường hợp.


10
Tại sao nên json.loadtránh sử dụng .loadsPython 3?
Zearin

10
Trang bạn liên kết không nói gì về việc tránh load.
Dan Hulme

28
Câu trả lời này đọc toàn bộ tệp vào bộ nhớ khi không phải và gợi ý rằng trong các tệp JSON 3 của Python có thể được đọc một cách lười biếng, điều này không đúng. Tôi xin lỗi, nhưng nó rõ ràng downvote.
Łukasz Rogalski

10
Câu trả lời này không chính xác. Không có lý do gì để không sử dụng json.load với trình xử lý tệp mở trong python3. Xin lỗi vì downvote, nhưng có vẻ như bạn không đọc kỹ các bình luận trên.
dusktreader

5
+1 Câu trả lời này rất hay! Cảm ơn bạn vì điều đó và kéo tôi đi xa vì đã tìm kiếm một chức năng có thể sử dụng chuỗi vì tôi chỉ làm việc với chuỗi và yêu cầu mạng không phải là tệp!
mới

54
data = []
with codecs.open('d:\output.txt','rU','utf-8') as f:
    for line in f:
       data.append(json.loads(line))

8
đây là giải pháp chính xác nếu bạn có nhiều đối tượng json trong một tệp. json.loadskhông giải mã nhiều đối tượng json. Nếu không, bạn sẽ gặp lỗi 'Dữ liệu bổ sung'.
yasin_alm

Đây là câu trả lời tốt nhất. Mặt khác, nó cung cấp lỗi 'Dữ liệu bổ sung'.
Earthx9

39
Có các đối tượng json mutlipl trong một tệp có nghĩa là chính tệp đó không thực sự hợp lệ json. Nếu bạn có nhiều đối tượng để đưa vào một tệp json, chúng sẽ được chứa trong một mảng ở cấp cao nhất của tệp.
dusktreader

Có nhiều đối tượng json trong một tệp có nghĩa là tệp không phải là một đối tượng json. Đó là một điều hiển nhiên. Tạo một mảng duy nhất trong số các đối tượng là một cách giải quyết rõ ràng. Nhưng JSON được thiết kế chấm dứt rõ ràng, ở hầu hết mọi cấp độ (bởi }, ]hoặc "). Do đó, bạn thực sự có thể nối nhiều đối tượng trong một chuỗi hoặc một tệp duy nhất mà không có sự mơ hồ. Vấn đề ở đây là một trình phân tích cú pháp mong đợi một đối tượng không thành công khi nó truyền nhiều hơn một đối tượng.
MSalters

Quảng cáo lưu trữ nhiều đối tượng JSON trong một tệp: có một "tiêu chuẩn" cho điều đó - jsonlines.org/examples trong .jsonl(dòng json), các đối tượng được phân tách bằng ký tự dòng mới, giúp xử lý trước để phân tích cú pháp tầm thường và cho phép để dễ dàng phân tách / bó tập tin mà không phải lo lắng về việc đánh dấu bắt đầu / kết thúc.
Sebi

13

"Ultra JSON" hoặc đơn giản là "ujson" có thể xử lý việc có []trong tệp JSON của bạn. Nếu bạn đang đọc tệp đầu vào JSON vào chương trình của mình dưới dạng danh sách các phần tử JSON; chẳng hạn như, [{[{}]}, {}, [], etc...]ujson có thể xử lý bất kỳ thứ tự tùy ý nào của danh sách từ điển, từ điển danh sách.

Bạn có thể tìm thấy ujson trong chỉ mục gói Python và API gần giống với jsonthư viện tích hợp của Python .

ujson cũng nhanh hơn nhiều nếu bạn đang tải các tệp JSON lớn hơn. Bạn có thể xem chi tiết hiệu năng so với các thư viện Python JSON khác trong cùng một liên kết được cung cấp.


9

Nếu bạn đang sử dụng Python3, bạn có thể thử thay đổi ( connection.jsontệp) JSON của mình thành:

{
  "connection1": {
    "DSN": "con1",
    "UID": "abc",
    "PWD": "1234",
    "connection_string_python":"test1"
  }
  ,
  "connection2": {
    "DSN": "con2",
    "UID": "def",
    "PWD": "1234"
  }
}

Sau đó, sử dụng mã sau đây:

connection_file = open('connection.json', 'r')
conn_string = json.load(connection_file)
conn_string['connection1']['connection_string_python'])
connection_file.close()
>>> test1

1
cái này cũng hoạt động trong 2.7.5
siddardha

17
Điều này để lại các tập tin xử lý mở. sử dụng một withtuyên bố sẽ tốt hơn
Corey Goldberg

6

Ở đây bạn đi với data.jsontập tin sửa đổi :

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": [{
        "id": "valore"
    }],
    "om_points": "value",
    "parameters": [{
        "id": "valore"
    }]
}

Bạn có thể gọi hoặc in dữ liệu trên bảng điều khiển bằng cách sử dụng các dòng dưới đây:

import json
from pprint import pprint
with open('data.json') as data_file:
    data_item = json.load(data_file)
pprint(data_item)

Sản lượng dự kiến ​​cho print(data_item['parameters'][0]['id']):

{'maps': [{'id': 'blabla', 'iscategorical': '0'},
          {'id': 'blabla', 'iscategorical': '0'}],
 'masks': [{'id': 'valore'}],
 'om_points': 'value',
 'parameters': [{'id': 'valore'}]}

Sản lượng dự kiến ​​cho print(data_item['parameters'][0]['id']):

valore

Nếu chúng ta muốn thêm một cột để đếm xem "bản đồ" có bao nhiêu quan sát, làm thế nào chúng ta có thể viết chức năng này?
Chenxi

5

Có hai loại trong phân tích cú pháp này.

  1. Phân tích dữ liệu từ một tệp từ đường dẫn hệ thống
  2. Phân tích cú pháp JSON từ URL từ xa.

Từ một tập tin, bạn có thể sử dụng như sau

import json
json = json.loads(open('/path/to/file.json').read())
value = json['key']
print json['value']

Arcticle này giải thích việc phân tích cú pháp đầy đủ và nhận các giá trị bằng hai kịch bản. Phân tích cú pháp JSON bằng Python


4

Là người dùng python3 ,

Sự khác biệt giữa loadloadsphương thức rất quan trọng đặc biệt khi bạn đọc dữ liệu json từ tệp.

Như đã nêu trong các tài liệu:

json.load:

Deserialize fp (a .read () - hỗ trợ tệp văn bản hoặc tệp nhị phân chứa tài liệu JSON) cho đối tượng Python bằng bảng chuyển đổi này.

json.loads:

json.loads: Deserialize s (một ví dụ str, byte hoặc bytearray chứa tài liệu JSON) cho một đối tượng Python sử dụng bảng chuyển đổi này.

Phương pháp json.load có thể đọc trực tiếp tài liệu json đã mở do có thể đọc tệp nhị phân.

with open('./recipes.json') as data:
  all_recipes = json.load(data)

Do đó, dữ liệu json của bạn có sẵn ở định dạng được chỉ định theo bảng chuyển đổi này:

https://docs.python.org/3.7/l Library / json.html # json-to-py-table


Làm thế nào đây là một câu trả lời cho câu hỏi được hỏi? Người dùng đã sử dụng đúng phương pháp để tải tập tin json.
Raj006
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.