Việc xác định các hàm trong kết quả JSON có hợp lệ không?


98

Một phần của phản hồi JSON của trang web có điều này (... được thêm vào ngữ cảnh):

{..., now:function(){return(new Date).getTime()}, ...}

Việc thêm các hàm ẩn danh vào JSON có hợp lệ không? Tôi mong đợi mỗi lần bạn truy cập 'thời gian' sẽ trả về một giá trị khác nhau.


Trình duyệt có phân tích cú pháp JSON thành công không? Nếu vậy thì có nó là hợp lệ (về mặt đó).
harschware

7
@harschware - điều đó chỉ đúng khi JSON liên quan đến javascript. Là một định dạng tuần tự hóa dữ liệu độc lập với ngôn ngữ, nó là sai và là một con đường có vấn đề để đi xuống.
jsoverson

@jsoverson - Tôi đồng ý. Xem câu trả lời của tôi dưới đây.
harschware

1
Dễ dàng để trả lời câu hỏi này cho mình: mở lên web bộ thanh tra và chạy: JSON.parse('{now:function(){return(new Date).getTime()}'). Người kiểm tra nói: Uncaught SyntaxError: Unexpected token nXem nhanh thông số JSON xác nhận điều này. Tập trung vào phần 'giá trị'.
Mark E. Haase,

Câu trả lời:


103

Không.

JSON hoàn toàn có nghĩa là một ngôn ngữ mô tả dữ liệu. Như đã lưu ý trên http://www.json.org , đây là một "định dạng trao đổi dữ liệu nhẹ". - không phải là một ngôn ngữ lập trình.

Theo http://en.wikipedia.org/wiki/JSON , "loại cơ bản" được hỗ trợ là:

  • Số (số nguyên, thực hoặc dấu phẩy động)
  • Chuỗi (Unicode được trích dẫn kép có thoát dấu gạch chéo ngược)
  • Boolean (đúng và sai)
  • Mảng (một chuỗi giá trị có thứ tự, được phân tách bằng dấu phẩy và được đặt trong dấu ngoặc vuông)
  • Đối tượng (tập hợp các cặp khóa: giá trị, được phân tách bằng dấu phẩy và được đặt trong dấu ngoặc nhọn)
  • null

2
@Dr. Zim, không và để so sánh mọi thứ với null những gì tôi làm là điều này a==null?1:a.toString()==""Điều này làm là nó nói nếu a = null thì nó trả về 1 / true, nếu nó là "" nghĩa là chuỗi trống bạn cũng nhận được 1 / true .. nếu nó là không phải null hoặc "" thì nó sẽ trả về 0 / false, bạn có thể sao chép điều này nhiều hơn để làm việc với [] và {} chỉ cần thêm ?1:a==[]?1:a.toString()=={}.toString();vào đoạn mã hiện tại của tôi. vì vậy có thể chức năng này sẽ giúp bạn. isnull=(function(a){return (a==null?1:a.toString()==""?1:a==[]?1:a.toString()=={}.toString())?true:false})Tôi sẽ sử dụng ?1:0thay vì ?true:falsebut (true / false)
JamesM-SiteGen

10
Đồng thời, các chức năng cũng là dữ liệu.
argyle

2
Tôi đã hạ cánh ở đây trong khi tìm cách tìm nạp "dữ liệu khác" bằng JSON. Sẽ rất tuyệt nếu thông báo cho khách hàng (từ máy chủ) cách lấy thêm dữ liệu, mà khách hàng không phải lo lắng về REST hoặc api nào sẽ gọi tiếp theo.
Ravindranath Akila

3
@RavindranathAkila REST ngụ ý rằng các lệnh gọi API tiếp theo có thể được hiển thị trong cuộc gọi. Nói cách khác: yêu cầu REST bạn đã làm, cho bạn biết những yêu cầu nào trong tương lai, bạn có thể muốn thực hiện (dựa trên logic quyết định của ứng dụng và dữ liệu). Một ví dụ hoàn hảo cho điều này là API Github, nơi các phần tử dữ liệu được trả về - nhưng một số phần tử trong số chúng dẫn đến các tài nguyên yêu cầu API khác.
Jens A. Koch

1
@ Jens-AndréKoch Cảm ơn! Sẽ kiểm tra nó
Ravindranath Akila

16

Vấn đề là JSON với tư cách là ngôn ngữ định nghĩa dữ liệu đã phát triển từ JSON dưới dạng Ký hiệu đối tượng JavaScript. Vì Javascript hỗ trợ eval trên JSON, nên đặt mã JSON bên trong JSON (trong trường hợp sử dụng đó) là hợp pháp. Nếu bạn đang sử dụng JSON để truyền dữ liệu từ xa, thì tôi sẽ nói rằng việc đưa các phương thức vào JSON là một phương pháp không tốt vì có thể bạn chưa mô hình hóa tốt sự tương tác giữa máy khách và máy chủ của mình. Và, xa hơn nữa, khi muốn sử dụng JSON làm ngôn ngữ mô tả dữ liệu, tôi có thể nói rằng bạn có thể gặp rắc rối khi nhúng các phương thức vì một số trình phân tích cú pháp JSON được viết chỉ với mô tả dữ liệu và có thể không hỗ trợ các định nghĩa phương thức trong cấu trúc.

Mục nhập JSON của Wikipedia tạo ra một trường hợp tốt cho việc không bao gồm các phương thức trong JSON, trích dẫn các mối quan tâm về bảo mật:

Trừ khi bạn hoàn toàn tin tưởng vào nguồn của văn bản và bạn có nhu cầu phân tích cú pháp và chấp nhận văn bản không hoàn toàn tuân thủ JSON, bạn nên tránh eval () và sử dụng JSON.parse () hoặc một trình phân tích cú pháp JSON cụ thể khác để thay thế. Trình phân tích cú pháp JSON sẽ chỉ nhận dạng văn bản JSON và sẽ từ chối văn bản khác, có thể chứa JavaScript ác ý. Trong các trình duyệt cung cấp hỗ trợ JSON gốc, trình phân tích cú pháp JSON cũng nhanh hơn nhiều so với eval. Dự kiến, hỗ trợ JSON gốc sẽ được đưa vào tiêu chuẩn ECMAScript tiếp theo.


2
Bạn có thể đang sử dụng thuật ngữ JSON một cách thông tục, nhưng chính thức "JSON" là một tiêu chuẩn ECMA không mã hóa các đối tượng chức năng. Không nên mơ hồ về khả năng bạn đang đề cập đến khi bạn nói "JSON" - đó là toàn bộ điểm của việc có một tiêu chuẩn.
Mark E. Haase,

Đồng ý rằng đó là sự thật ngày hôm nay. Tôi không có nguồn để trích dẫn, nhưng tôi tin rằng JSON là một thuật ngữ được đặt ra trước khi ECMA xuất hiện trong trò chơi Javascript và trước khi JSON là một định dạng trao đổi dữ liệu tiêu chuẩn ... do đó tôi đã sử dụng thuật ngữ 'tiến hóa'
harschware

@harschware Theo RFC 4627, JSON được tạo từ ECMA.
Jenna Sloan

9

Hãy trích dẫn một trong những thông số kỹ thuật - http://tools.ietf.org/html/rfc7159#section-12

Các đối tượng JavaScript Notation (JSON) Data Interchange Format Thông số kỹ thuật quốc gia:

JSON là một tập hợp con của JavaScript nhưng không bao gồm phép gán và lệnh gọi.

Vì cú pháp của JSON được mượn từ JavaScript, nên có thể sử dụng hàm "eval ()" của ngôn ngữ đó để phân tích cú pháp văn bản JSON. Điều này thường tạo thành một rủi ro bảo mật không thể chấp nhận được, vì văn bản
có thể chứa mã thực thi cùng với các khai báo dữ liệu
. Việc xem xét tương tự cũng áp dụng cho việc sử dụng các hàm giống eval () trong bất kỳ ngôn ngữ lập trình nào khác trong đó các văn bản JSON tuân theo
cú pháp của ngôn ngữ đó .

Vì vậy, tất cả các câu trả lời trạng thái nào, các hàm đó không thuộc tiêu chuẩn JSON đều đúng.

Câu trả lời chính thức là: Không, không hợp lệ để xác định các hàm trong kết quả JSON!


Câu trả lời có thể là có, bởi vì "mã là dữ liệu" và "dữ liệu là mã". Ngay cả khi JSON được sử dụng như một định dạng tuần tự hóa dữ liệu độc lập với ngôn ngữ, thì việc truyền "mã" qua các kiểu khác sẽ hoạt động.

Một chuỗi JSON có thể được sử dụng để chuyển một hàm JS đến trình duyệt phía máy khách để thực thi.

[{"data":[["1","2"],["3","4"]],"aFunction":"function(){return \"foo bar\";}"}]

Điều này dẫn đến câu hỏi như: Làm thế nào để " Thực thi mã JavaScript được lưu trữ dưới dạng một chuỗi ".

Hãy chuẩn bị để nâng cờ "eval () là ác" của bạn và dán cờ "không tạo đường hầm qua JSON" bên cạnh cờ đó.



4

Không, chắc chắn là không.

Nếu bạn sử dụng một trình tuần tự JSON phù hợp, nó sẽ không cho phép bạn tuần tự hóa một chức năng như vậy. Đó là một ĐỐI TƯỢNG hợp lệ, nhưng không phải là JSON hợp lệ. Dù mục đích của trang web đó là gì, nó không gửi JSON hợp lệ.


2
Tôi sử dụng JSON-Lib và coi nó là một bộ nối tiếp tuyệt vời. Từ [Trang sử dụng] (json-lib.sourceforge.net/usage.html), bạn có thể nhìn thấy nó sẽ serialize chức năng tốt
harschware

Thật thú vị ... Tôi chưa bao giờ thấy điều đó trước đây. Nó chắc chắn không phải là đặc tả ( json.org nói rõ ràng rằng JSON là ngôn ngữ độc lập, định nghĩa hàm nào thì không), nhưng vẫn thú vị.
jvenema

Thật buồn cười mà nó cho là ngôn ngữ độc lập nhưng JSON là viết tắt của JavaScript Object Notation hmm lạ ..
Nate-Wilkins

3

JSON loại trừ các hàm một cách rõ ràng vì nó không có nghĩa là một cấu trúc dữ liệu chỉ JavaScript (mặc dù có JS trong tên).


3

Một câu trả lời ngắn gọn là KHÔNG ...

JSON là một định dạng văn bản hoàn toàn độc lập với ngôn ngữ nhưng sử dụng các quy ước quen thuộc với các lập trình viên thuộc họ ngôn ngữ C, bao gồm C, C ++, C #, Java, JavaScript, Perl, Python và nhiều ngôn ngữ khác. Các thuộc tính này làm cho JSON trở thành một ngôn ngữ trao đổi dữ liệu lý tưởng.

Nhìn vào lý do tại sao:

Khi trao đổi dữ liệu giữa trình duyệt và máy chủ, dữ liệu chỉ có thể là văn bản.

JSON là văn bản và chúng tôi có thể chuyển đổi bất kỳ đối tượng JavaScript nào thành JSON và gửi JSON đến máy chủ.

Chúng tôi cũng có thể chuyển đổi bất kỳ JSON nào nhận được từ máy chủ thành các đối tượng JavaScript.

Bằng cách này, chúng tôi có thể làm việc với dữ liệu dưới dạng các đối tượng JavaScript mà không cần phân tích cú pháp và dịch phức tạp.

Nhưng đợi đã ...

Vẫn có những cách để lưu trữ hàm của bạn, điều đó không được khuyến khích rộng rãi , nhưng vẫn có thể:

Chúng tôi đã nói, bạn có thể tiết kiệm một string... còn việc chuyển đổi hàm của bạn thành một chuỗi thì sao?

const data = {func: '()=>"a FUNC"'};

Sau đó, bạn có thể xâu chuỗi dữ liệu bằng cách sử dụng JSON.stringify(data)và sau đó sử dụng JSON.parseđể phân tích cú pháp nó (nếu cần đến bước này) ...

eval để thực thi một hàm chuỗi (trước khi làm điều đó, chỉ cho bạn biết bằng cách sử dụng eval không được khuyến nghị rộng rãi):

eval(data.func)(); //return "a FUNC"

0

Thông qua việc sử dụng NodeJS (cú pháp commonJS), tôi đã có thể làm cho loại chức năng này hoạt động, ban đầu tôi chỉ có một cấu trúc JSON bên trong một số tệp JS bên ngoài, nhưng tôi muốn cấu trúc đó giống với một Lớp hơn, với các phương thức có thể được quyết định tại thời gian chạy.

Không bắt buộc phải khai báo 'Executor' trong myJSON.

var myJSON = {
    "Hello": "World",
    "Executor": ""
}

module.exports = {
    init: () => { return { ...myJSON, "Executor": (first, last) => { return first + last } } }
}

-3

Các biểu thức hàm trong JSON hoàn toàn có thể thực hiện được, chỉ cần đừng quên đặt nó trong dấu ngoặc kép. Đây là một ví dụ được lấy từ thiết kế cơ sở dữ liệu noSQL:

{
  "_id": "_design/testdb",
  "views": {
    "byName": {
      "map": "function(doc){if(doc.name){emit(doc.name,doc.code)}}"
    }
  }
}


Câu hỏi là về một hàm không phải là một chuỗi. JSON hỗ trợ các giá trị chuỗi, nhưng nó không hỗ trợ các hàm. Xem câu trả lời của Mike để biết chi tiết
Jannis

@jannis nó có thể mặc dù. nếu bạn thêm một chức năng tự gọi như. mọi người ở đây dường như không biết câu trả lời.
Roj

-4

mặc dù eval không được khuyến khích, điều này hoạt động:

<!DOCTYPE html>
<html>
<body>

<h2>Convert a string written in JSON format, into a JavaScript function.</h2>

<p id="demo"></p>

<script>
    function test(val){return val + " it's OK;}
    var someVar = "yup";
    var myObj = { "func": "test(someVar);" };
    document.getElementById("demo").innerHTML = eval(myObj.func);
</script>

</body>
</html>

1
đã bỏ phiếu vì không cần thiết phải sử dụng HTML trong ví dụ này, đây là kiểu mã hóa 5 năm tuổi, thiếu một câu trích dẫn và, các tệp JSON không được phép chứa các hàm, nếu có thì chúng không thể được tuần tự hóa hoặc được lưu trữ trong một không sql DB,
Martijn Scheffer

-5

Bỏ dấu ngoặc kép ...

var a = {"b":function(){alert('hello world');} };

a.b();

Đây là JavaScript, câu hỏi đang hỏi về JSON.
Quentin
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.