2012-05-13 48 views
9

Cuộc gọi AJAX trả về văn bản phản hồi bao gồm chuỗi JSON. Tôi cần phải:Trích xuất JSON từ văn bản

  1. trích xuất các chuỗi JSON
  2. sửa đổi nó
  3. sau đó lắp lại nó để cập nhật các chuỗi gốc

Tôi không quá lo lắng về bước 2 và 3, nhưng tôi có thể 't tìm hiểu làm thế nào để làm bước 1. Tôi đã suy nghĩ về việc sử dụng một biểu thức chính quy, nhưng tôi không biết làm thế nào như JSON của tôi có thể có nhiều cấp độ với các đối tượng lồng nhau hoặc mảng.

+2

Bạn không phải là người mới ở đây. Bạn đã thử cái gì? Câu trả lời của bạn trông như thế nào? –

+0

Ngoài ra, RegEx có lẽ không phải là công cụ chính xác cho công việc. –

+0

@Truth Cách giải quyết duy nhất của tôi cho đến nay là bao gồm các điểm đánh dấu trong văn bản phản hồi để hiển thị phần đầu và phần cuối của chuỗi JSON. Không có gì để tự hào hoặc điều đó sẽ hướng dẫn câu trả lời. – Christophe

Trả lời

9

Bạn không thể sử dụng regex để trích xuất JSON từ văn bản tùy ý. Vì các regex thường là not powerful enough to validate JSON (trừ khi bạn có thể sử dụng PCRE), chúng cũng không thể khớp với nó - nếu có thể, chúng cũng có thể xác thực JSON.

Tuy nhiên, nếu bạn biết rằng phần tử cấp cao nhất của JSON của bạn luôn luôn là một đối tượng hoặc mảng, bạn có thể đi bằng các phương pháp sau đây:

  • Tìm việc mở đầu tiên ({ hoặc [) và cuối cùng đóng (} hoặc ]) cú đúp trong chuỗi của bạn.
  • Hãy thử phân tích cú pháp khối văn bản đó (bao gồm cả dấu ngoặc ôm) bằng cách sử dụng JSON.parse(). Nếu nó thành công, kết thúc và trả về kết quả được phân tích cú pháp.
  • Lấy dấu ngoặc đóng trước đó và thử phân tích chuỗi đó. Nếu nó thành công, bạn được thực hiện một lần nữa.
  • Lặp lại thao tác này cho đến khi bạn không có cú đúp hoặc cái nào xuất hiện trước dấu ngoặc đang mở.
  • Tìm dấu ngoặc mở đầu tiên sau dấu ngoặc đơn từ bước 1. Nếu bạn không tìm thấy bất kỳ, chuỗi không chứa đối tượng/mảng JSON và bạn có thể dừng lại.
  • Chuyển đến bước 2.

Đây là chức năng trích xuất đối tượng JSON và trả về đối tượng và vị trí của đối tượng. Nếu bạn thực sự cần mảng cấp cao nhất, cũng vậy, nó phải được mở rộng:

function extractJSON(str) { 
    var firstOpen, firstClose, candidate; 
    firstOpen = str.indexOf('{', firstOpen + 1); 
    do { 
     firstClose = str.lastIndexOf('}'); 
     console.log('firstOpen: ' + firstOpen, 'firstClose: ' + firstClose); 
     if(firstClose <= firstOpen) { 
      return null; 
     } 
     do { 
      candidate = str.substring(firstOpen, firstClose + 1); 
      console.log('candidate: ' + candidate); 
      try { 
       var res = JSON.parse(candidate); 
       console.log('...found'); 
       return [res, firstOpen, firstClose + 1]; 
      } 
      catch(e) { 
       console.log('...failed'); 
      } 
      firstClose = str.substr(0, firstClose).lastIndexOf('}'); 
     } while(firstClose > firstOpen); 
     firstOpen = str.indexOf('{', firstOpen + 1); 
    } while(firstOpen != -1); 
} 

var obj = {'foo': 'bar', xxx: '} me[ow]'}; 
var str = 'blah blah { not {json but here is json: ' + JSON.stringify(obj) + ' and here we have stuff that is } really } not ] json }} at all'; 
var result = extractJSON(str); 
console.log('extracted object:', result[0]); 
console.log('expected object :', obj); 
console.log('did it work  ?', JSON.stringify(result[0]) == JSON.stringify(obj) ? 'yes!' : 'no'); 
console.log('surrounding str :', str.substr(0, result[1]) + '<JSON>' + str.substr(result[2])); 

Demo (thực hiện trong môi trường nodejs, nhưng nên làm việc trong một trình duyệt, quá): https://paste.aeum.net/show/81/

+0

Thú vị ... Liên kết của bạn đang trỏ đến một trang có nội dung "Có, bạn có thể hoàn thành việc xác thực regex hoàn chỉnh"! – Christophe

+0

Oh heh, không cuộn qua câu trả lời được chấp nhận - nhưng tốt, PCRE là khá mạnh mẽ. Tôi không nghĩ rằng các tính năng đó có sẵn trong JavaScript. – ThiefMaster

0

Nếu JSON được trả lại như một phần của phản hồi ajax, tại sao không sử dụng phân tích cú pháp JSON gốc của trình duyệt (hãy xem xét gotchas)? Hoặc jQuery JSON Parsing?

Nếu JSON hoàn toàn bị xáo trộn với văn bản, điều đó thực sự reeks của một vấn đề thiết kế IMHO - nếu bạn có thể thay đổi nó, tôi mạnh mẽ khuyên bạn nên làm như vậy (tức là trả về một đối tượng JSON như phản hồi, với văn bản làm tài sản của đối tượng).

Nếu không, sau đó sử dụng RegEx sẽ là một cơn ác mộng tuyệt đối. JSON tự nhiên rất linh hoạt và việc phân tích cú pháp chính xác sẽ không chỉ tốn thời gian mà còn lãng phí. Tôi có lẽ sẽ đưa vào đánh dấu nội dung ở đầu/cuối và hy vọng cho tốt nhất. Nhưng bạn sẽ mở rộng để xác thực lỗi, v.v.

+0

Rất tiếc, tôi không thể thay đổi. Những gì tôi nhận được trong phản hồi thực sự là một kịch bản toàn bộ bao gồm các tham số trong một JSON literal. – Christophe

+0

Tôi đang bối rối, vì trong nhận xét của bạn về câu hỏi, bạn đã thêm điểm đánh dấu vào đầu/cuối của chuỗi JSON? Làm thế nào bạn làm điều đó mà không thể thay đổi phản ứng? –

+0

Xin lỗi, ý tôi là tôi không thể ngăn không cho JSON được trộn lẫn với "văn bản", văn bản thực sự là một tập lệnh. – Christophe

1

Đối với những người đang tìm kiếm (như tôi) để trích chuỗi JSON từ văn bản nói chung (ngay cả khi chúng không hợp lệ), bạn có thể xem plugin Gulp này https://www.npmjs.com/package/gulp-extract-json-like.Nó tìm kiếm tất cả các chuỗi có vẻ như được định dạng như chuỗi JSON.

Tạo thư mục và cài đặt gói.

mkdir project && cd project 
npm install gulp gulp-extract-json-like 

Tạo một file ./gulpfile.js và đưa nội dung sau vào nó:

var gulp = require('gulp'); 
var extractJsonLike = require('gulp-extract-json-like'); 

gulp.task('default', function() { 
    return gulp.src('file.txt') 
    .pipe(extractJsonLike()) 
    .pipe(gulp.dest('dist')); 
}); 

Tạo một tập tin gọi là ./file.txt chứa văn bản của bạn và chạy lệnh sau.

gulp 

Tìm thấy chuỗi JSON sẽ ở trong ./dist/file.txt.

Các vấn đề liên quan