2011-02-03 35 views
9

Tôi cần phân tích cú pháp JSON không hợp lệ trong Ruby.Cách phân tích cú pháp JSON không hợp lệ bằng các khóa không được kiểm soát bằng ActiveSupport 3 (Rails)

Cái gì như:

json_str = '{name:"Javier"}' 
ActiveSupport::JSON.decode json_str 

Như bạn có thể thấy, đó là không hợp lệ vì chìa khóa băm không được trích dẫn, nó phải là

json_str = '{"name":"Javier"}' 

Nhưng điều đó không thể thay đổi và tôi phải phân tích các phím không được kiểm soát.

Tôi có thể phân tích cú pháp bằng ActiveSupport 2.x, nhưng ActiveSupport 3 không cho phép tôi. Nó ném cho tôi:

Yajl::ParseError: lexical error: invalid string in json text. 
             {name:"Javier"} 
        (right here) ------^ 

Bằng cách này, nó là một ứng dụng của Ruby sử dụng một số thư viện Rails, nhưng nó không phải là một ứng dụng Rails

Cảm ơn trước

+0

Json không hợp lệ này đến từ đâu? Một phần còn lại api hoặc một số tập tin? Nó sẽ là tốt nhất để thực sự sửa chữa các json, một phân tích cú pháp chấp nhận json không hợp lệ là xấu và tôi vui vì họ đang sử dụng Yajl bây giờ. –

+0

Vâng, đó là một API. Và yeah nó stinks rằng tôi phải thực hiện một workaround cho điều này nhưng tôi không có bất kỳ liên hệ với các nhà phát triển của API. –

Trả lời

0

Something như thế này?

require 'json' 
json_str = '{name:"Javier"}' 
hash = JSON::parse(json_str.gsub(/{|:"/, {'{'=>'{"', ':"'=>'":"'})) 
+0

Wow Tôi nghĩ rằng tôi có thể sửa chữa mà không cần phân tích cú pháp JSON (có thể kích hoạt một số loại cờ ActiveSupport). Tôi sẽ xem xét kỹ hơn mã đó và cho bạn biết nó hoạt động như thế nào đối với tôi. –

+0

xin lỗi, nó đã cho tôi một ngoại lệ SyntaxError: 'biểu thức chính quy không hợp lệ; không có mẫu trước đó, mà '{' sẽ xác định cardinality tại 1:/{|: "/' –

2

Tôi sẽ sử dụng một biểu thức chính quy để sửa chữa JSON không hợp lệ này:

json_str = '{name:"Javier"}' 
json_str.gsub!(/(['"])?([a-zA-Z0-9_]+)(['"])?:/, '"\2":') 
hash = Yajl::Parser.parse(json_str) 
0

Dưới đây là một regex hơi mạnh mẽ, bạn có thể sử dụng. Nó không hoàn hảo - đặc biệt là nó không hoạt động trong một số trường hợp góc nơi các giá trị bản thân chứa văn bản json-như thế nào, nhưng nó sẽ làm việc trong trường hợp tổng quát nhất:

quoted_json = unquoted_json.gsub(/([{,]\s*)(\w+)(\s*:\s*["\d])/, '\1"\2"\3') 

Đầu tiên nó sẽ tìm kiếm hoặc là một { hoặc , đó là các tùy chọn cho ký tự đứng trước tên khóa (cũng cho phép bất kỳ khoảng trắng nào có số \s*). Nó nắm bắt điều này như một nhóm:

([{,]\s*) 

Sau đó, nó nắm bắt được chính bản thân, trong đó bao gồm các chữ cái, chữ số và dấu gạch dưới (mà regex thuận tiện cung cấp một lớp \w ký tự cho):

(\w+) 

Cuối cùng, nó khớp với những gì phải tuân theo một tên khóa; tức là dấu hai chấm theo sau là dấu ngoặc kép (cho giá trị chuỗi) hoặc chữ số (cho giá trị số). Cũng cho phép khoảng trống thừa, và nắm bắt được toàn bộ sự việc trong một nhóm:

(\s*:\s*["\d]) 

Đối với mỗi trận đấu, nó chỉ đưa ba mảnh lại với nhau, nhưng với dấu ngoặc kép quanh phím (để dấu ngoặc kép quanh nhóm chụp 2 #):

'\1"\2"\3' 
Các vấn đề liên quan