2013-05-03 38 views
5

Tôi đang làm việc với các hệ thống điều khiển "thoải mái" dữ liệu JSON trong đó bao gồm vỏ kiểu # dòng bình luận:Processing comments vỏ kiểu trong JSON

[ 
    { 
    # Batman 
    "first-name": "Bruce", 
    "last-name": "Wayne" 
    }, 
    { 
    # Superman 
    "first-name": "Clark", 
    "last-name": "Kent" 
    } 
] 

Các phần của hệ thống tôi đang làm việc trên công dụng json-lib - điều mà tôi ngạc nhiên khi khám phá là chấp nhận các nhận xét kiểu vỏ - để phân tích đầu vào JSON.

tôi cần phải trích xuất một số chú thích bổ sung từ những ý kiến, nhưng json-lib dường như chỉ loại bỏ chúng mà không cung cấp API dùng để đọc chúng:

JSONObject map = (JSONObject)JSONSerializer.toJSON("{\n"+ 
                " # Batman\n" + // note the shell-style # comment 
                " \"first-name\": \"Bruce\",\n" + 
                " \"last-name\": \"Wayne\"\n" + 
                "}"); 
System.out.println(map.toString()); 
/* <<'OUTPUT' 
* {"first-name":"Bruce","last-name":"Wayne"} 
* OUTPUT 
* note the absence of the shell-style comment 
*/ 

này có ý nghĩa kể từ khi bình luận không phải là một phần của JSON spec và tôi json-lib may mắn không chỉ bị nghẹt thở khi phân tích cú pháp chúng ngay từ đầu.

Đáng chú ý:

  • các hệ thống khác tiêu thụ cùng JSON này và các chú thích cần phải được minh bạch đối với họ, vì vậy cấu trúc JSON không thể được sửa đổi bằng cách thêm thuộc tính cho ý kiến ​​để thay thế.
  • không phải tất cả các thành phần và đối tượng trong hệ thống của tôi đều có quyền truy cập vào nguồn JSON thô: một thành phần đọc tệp và phân tích cú pháp bằng JSONlib và chuyển các bản đồ đã được tuần tự hóa v.v.

Làm cách nào để đọc và phân tích những nhận xét này trong khi xử lý đầu vào JSON? Có một thư viện mà sẽ cho phép tôi đọc chúng và liên kết chúng với vị trí của chúng trong JSON - tôi có thể dễ dàng kết nối nhận xét Batman với mục nhập "Bruce Wayne" không?

Tôi hiện đang sử dụng json-lib, nhưng tôi đang mở để điều tra các thư viện JSON khác và mở bằng các ngôn ngữ khác mở rộng JSON, chẳng hạn như YAML - nhưng tôi không chắc những công cụ này sẽ cho phép tôi đọc và xử lý các bình luận trong đầu vào của tôi.

+0

http://www.lifl.fr/~riquetd/parse-a-json-file-with-comments.html Liên kết này sử dụng regex: ''(^)? [^ \ S \ n] */(?: \ * (. *?) \ */[^ \ S \ n] * |/[^ \ n] *) ($)? ''Để xóa nhận xét. Tất nhiên bạn có thể sử dụng cùng một regex cho các mục đích khác. –

+0

@remyabel - Không phải tất cả các thành phần và đối tượng trong hệ thống của tôi đều có quyền truy cập vào nguồn JSON thô: một thành phần đọc tệp và phân tích cú pháp bằng JSONlib và chuyển các bản đồ đã được tuần tự hóa v.v. –

+2

bạn luôn có thể không đặt dữ liệu có ý nghĩa vào vị trí "vứt bỏ"? giống như tôi không lưu trữ những thứ quan trọng của tôi trong thùng rác bên ngoài nhà của tôi ... – jtahlborn

Trả lời

4

gì tôi đã chọn để làm là thay đổi phạm vi công cộng Thư viện JSON.org để hỗ trợ vỏ bình luận và bình luận thêm vào đối tượng JSON, như tôi đã làm trong ý chính này GitHub:

https://gist.github.com/peteroupc/5529464

Ví dụ về sử dụng:

JSONObject obj=new JSONObject("{ # Comment\n"+ 
     "\"first-key\":\"first-value\",\n"+ 
     "\"second-key\":\"second-value\" }", 
     JSONObject.OPTION_SHELL_COMMENTS | // Support SHELL-style comments 
     JSONObject.OPTION_ADD_COMMENTS // Incorporate comments in the JSON object 
); 
System.out.println(obj); // Output the JSON object 

Kết quả ví dụ. Lưu ý rằng nhận xét xảy ra trong một khóa được gọi là "@comment".

{"second-key":"second-value","@comment":"Comment","first-key":"first-value"} 

Nhưng một trong các yêu cầu của bạn là "không thể sửa đổi cấu trúc JSON bằng cách thêm thuộc tính cho nhận xét thay thế". Điều đó có nghĩa là các chú thích phải được liên kết với các đối tượng JSON theo một cách khác. May mắn thay, một đặc tả được gọi là JSON Pointer gần đây đã được xuất bản như RFC 6901. JSON Pointer là một chuỗi tham chiếu đến một đối tượng JSON trong một đối tượng JSON khác. Theo đó, các bước bổ sung là bắt buộc: tìm các đối tượng con bằng các phím "@comment", xóa các khóa và tạo ánh xạ các con trỏ JSON tới các nhận xét.

Điều này được minh họa bằng mã bên dưới.

// Objects with comments associated with them will 
// now contain an "@comment" key; get the JSON Pointers 
// (RFC6901) to these objects and remove the "@comment" keys. 
Map<String,Object> pointers=JSONPointer.getPointersWithKeyAndRemove(obj,"@comment"); 
// For each JSON Pointer, get its corresponding object. 
// They will always be JSONObjects. 
for(String pointer : pointers.keySet()){ 
    JSONObject subobj=(JSONObject)JSONPointer.getObject(obj,pointer); 
    System.out.println(subobj); // Output the object 
    System.out.println(pointers.get(pointer)); // Output the key's value 
} 

Ví dụ đầu ra:

{"second-key":"second-value","first-key":"first-value"} 
Comment 

Kể từ khi JSON Pointer là mới, tôi đã viết thực hiện riêng của tôi về nó và đưa nó vào ý chính GitHub.


Dưới đây là các ví dụ khác để làm rõ.

Với mảng này JSON (sử dụng JSONArray thay vì JSONObject trong ví dụ này):

[{ # foo 
"foo-key":"foo-value"}, 
{ # This is a 
# quite long comment. 
"bar-key":"bar-value"}] 

Kết quả sẽ là:

{"foo-key":"foo-value"} 
foo 
{"bar-key":"bar-value"} 
This is a quite long comment. 

Do vậy, nhiều ý kiến ​​được kết hợp lại thành một bình luận duy nhất . Nhưng với JSON Mảng này:

[{ # foo 
"foo-key":"foo-value"}, 
{ # This is a 
# quite long comment. 
"bar-key":"bar-value" 
# This is another comment. 
    }] 

Kết quả sẽ là:

{"foo-key":"foo-value"} 
foo 
{"bar-key":"bar-value"} 
This is another comment. 

Do vậy, nhiều ý kiến ​​đã xảy ra ở nhiều nơi trên đối tượng "thanh" không được kết hợp từ.

+0

Chỉ để kiểm tra xem tôi có hiểu hay không: điều này chỉ cho phép một nhận xét cho mỗi đối tượng? –

+0

Việc triển khai hiện tại kết hợp các nhận xét xảy ra ngay cạnh nhau, nhưng không phải các nhận xét xảy ra ở các vị trí khác nhau trong cùng một đối tượng phụ. Tôi sẽ làm rõ điều này với các ví dụ khác. –

+0

Bạn có thể cho tôi biết liệu giải pháp này có phù hợp với bạn không? –

0

các hệ thống khác tiêu thụ cùng JSON này và các chú thích cần phải được minh bạch đối với họ, vì vậy cấu trúc JSON không thể được sửa đổi bằng cách thêm thuộc tính cho ý kiến ​​thay vì

Sử dụng ý kiến ​​trong các tin nhắn để truyền dữ liệu giữa các hệ thống dường như không phải là một thực hành tốt. . Ví dụ. XML sẽ không hỗ trợ điều đó.

Tại sao không chỉ kết hợp các "nhận xét" quan trọng dưới dạng dữ liệu? Đó là những gì nó là nếu hệ thống khác đang sử dụng nó. : ^)

+0

"Sử dụng các nhận xét trong các thông điệp để truyền dữ liệu giữa các hệ thống dường như không phải là một phương pháp hay." Đã đồng ý. Đối với "nếu hệ thống khác đang sử dụng nó": ý tôi là "chú thích cần minh bạch với chúng" là dữ liệu nhận xét không thể trong JSON là nó không thể được thêm vào như một khóa mới đối tượng JSON - sau đó hệ thống khác sẽ xử lý các chú thích mà chúng không được yêu cầu. –

+0

Ah, tôi hiểu rồi. Vì vậy, nhận xét không được sử dụng làm dữ liệu. Tất cả đều tốt. :) –