2016-01-15 16 views
5

Tôi đang cạo một số từ điển JSONP từ AWS (từ tệp javascript). Sau khi phân tích cú pháp dữ liệu thô chỉ cho dữ liệu giống JSON, trong một số trường hợp, tôi nhận được JSON hợp lệ và có thể tải thành công dữ liệu này bằng Python (json_data = json.loads(json_like_data)). Tuy nhiên, một số JSONP của Amazon không bao gồm dấu ngoặc kép quanh khóa của chúng (xem phần sau).Python: JSON không hợp lệ - Các khóa không được trích dẫn

... 
{type:"storageCurrentGen",sizes: 
[{size:"i2.xlarge",vCPU:"4",ECU:"14",memoryGiB:"30.5",storageGB:"1 x 800 SSD",valueColumns:[{name:"linux",prices:{USD:"0.938"}}]}, 
{size:"i2.2xlarge",vCPU:"8",ECU:"27",memoryGiB:"61",storageGB:"2 x 800 SSD",valueColumns:[{name:"linux",prices:{USD:"1.876"}}]}, 
{size:"i2.4xlarge",vCPU:"16",ECU:"53",memoryGiB:"122",storageGB:"4 x 800 SSD",valueColumns:[{name:"linux",prices:{USD:"3.751"}}]}, 
... 

Đối với JSONP, điều này vẫn hoạt động như cú pháp JavaScript hợp lệ. Tuy nhiên, mã vạch json.loads(json_str) của Python không phù hợp vì nó không hợp lệ JSON.

Có một mô-đun Python YAML khác có thể xử lý các khóa không được kiểm soát, NHƯNG phải có dấu cách sau dấu chấm phẩy (:).

Tôi cho rằng tôi có hai tùy chọn.

  1. Bằng cách nào đó thay thế nhân vật ở giữa một cú đúp mở hoặc dấu phẩy ({ | ,) và dấu hai chấm (:). Sau đó sử dụng json.loads(...).
  2. Thêm dấu cách sau dấu hai chấm (:). Sau đó phân tích cú pháp với yaml.load(...).

Tôi đoán rằng tùy chọn 2 tốt hơn 1. Tuy nhiên, tôi đang tìm kiếm gợi ý về giải pháp tốt hơn.

Có ai gặp phải JSON có định dạng không đúng như trước đây và sử dụng Python để phân tích cú pháp không?

+4

Ngay cả đối với Javascript, nó là ** không ** JSON hợp lệ. Đó là JavaScript hợp lệ, điều này không hoàn toàn giống nhau. –

+0

@MartijnPieters Ah. Cảm ơn vì bạn đã làm sáng tỏ. – dlstadther

Trả lời

13

Bạn có thể cài đặt và sử dụng demjson library; nó hỗ trợ phân tích cú pháp hợp lệ Javascript (thiếu dấu ngoặc kép):

import demjson 

result = demjson.decode(jsonp_payload) 

Chỉ khi bạn đặt cờ strict=True không demjson từ chối để phân tích đầu vào của bạn:

>>> import demjson 
>>> demjson.decode('{javascript_style:"Look ma, no quotes!"}') 
{u'javascript_style': u'Look ma, no quotes!'} 
>>> demjson.decode('{javascript_style:"Look ma, no quotes!"}', strict=True) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Users/mjpieters/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/demjson.py", line 5701, in decode 
    return_stats=(return_stats or write_stats)) 
    File "/Users/mjpieters/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/demjson.py", line 4917, in decode 
    raise errors[0] 
demjson.JSONDecodeError: ('JSON does not allow identifiers to be used as strings', u'javascript_style') 

Sử dụng một biểu thức chính quy bạn có thể thử regex theo cách của bạn thành JSON hợp lệ; Tuy nhiên, điều này có thể dẫn đến sai tích cực. Các mô hình sẽ là:

import re 

valid_json = re.sub(r'(?<={|,)([a-zA-Z][a-zA-Z0-9]*)(?=:)', r'"\1"', jsonp_payload) 

này phù hợp với { hoặc ,, tiếp theo là một định danh JavaScript (một nhân vật, tiếp theo là nhiều ký tự hoặc chữ số), và sau đó trực tiếp bằng dấu hai chấm :. Nếu các giá trị được trích dẫn của bạn chứa bất kỳ mẫu nào như vậy, bạn sẽ nhận được JSON không hợp lệ.

+0

#impressedwiththatspeed Cảm ơn bạn rất nhiều vì đã trả lời nhanh chóng và kỹ lưỡng! – dlstadther

2

Bạn cũng có thể làm điều đó (trong trường hợp đặc biệt này) với Regex đơn giản:

ll = '{type:"storageCurrentGen",sizes:\n[{size:"i2.xlarge",vCPU:"4",ECU:"14",memoryGiB:"30.5",storageGB:"1 x 800 SSD",valueColumns:[{name:"linux",prices:{USD:"0.938"}}]},\n{size:"i2.2xlarge",vCPU:"8",ECU:"27",memoryGiB:"61",storageGB:"2 x 800 SSD",valueColumns:[{name:"linux",prices:{USD:"1.876"}}]},\n{size:"i2.4xlarge",vCPU:"16",ECU:"53",memoryGiB:"122",storageGB:"4 x 800 SSD",valueColumns:[{name:"linux",prices:{USD:"3.751"}}]},' 

ll_patched = re.sub('([{,:])(\w+)([},:])','\\1\"\\2\"\\3',ll) 
>>> ll_patched 
'{"type":"storageCurrentGen","sizes":\n[{"size":"i2.xlarge","vCPU":"4","ECU":"14","memoryGiB":"30.5","storageGB":"1 x 800 SSD","valueColumns":[{"name":"linux","prices":{"USD":"0.938"}}]},\n{"size":"i2.2xlarge","vCPU":"8","ECU":"27","memoryGiB":"61","storageGB":"2 x 800 SSD","valueColumns":[{"name":"linux","prices":{"USD":"1.876"}}]},\n{"size":"i2.4xlarge","vCPU":"16","ECU":"53","memoryGiB":"122","storageGB":"4 x 800 SSD","valueColumns":[{"name":"linux","prices":{"USD":"3.751"}}]},' 
Các vấn đề liên quan