Chuyển đổi chuỗi đối tượng thành JSON


165

Làm cách nào tôi có thể chuyển đổi một chuỗi mô tả một đối tượng thành một chuỗi JSON bằng JavaScript (hoặc jQuery)?

ví dụ: Chuyển đổi cái này ( KHÔNG phải là chuỗi JSON hợp lệ):

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }"

vào đây:

str = '{ "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] }'

Tôi rất thích tránh sử dụng eval()nếu có thể.


Tại sao chuỗi của bạn không hợp lệ JSON ở vị trí đầu tiên? Làm thế nào bạn tạo ra điều đó?
Tên lửa Hazmat

2
Chuỗi được lưu trữ trong một data-attrubute, như thế này: <div data-object="{hello:'world'}"></div>và tôi không muốn sử dụng các trích dẫn đơn trong HTML (vì vậy có lẽ nó không đáng tin cậy)
snorpey

5
@snorpey: <div data-object='{"hello":"world"}'></div>là HTML hợp lệ 100% (trích dẫn đơn có liên quan gì đến việc tin tưởng nó hay không?). Nếu bạn làm theo cách này, bạn có thể làm được JSON.parsevà nó sẽ hoạt động tốt. Lưu ý: các phím cũng cần được trích dẫn.
Tên lửa Hazmat

@Rocket cảm ơn những nỗ lực của bạn! Tôi chỉ muốn tìm cách xoay quanh việc phải sử dụng các trích dẫn đơn trong HTML (mặc dù nó hợp lệ 100%) và ký hiệu JSON.
snorpey

@snorpey: Cách đầu tiên là không đặt JSON vào thuộc tính HTML ở vị trí đầu tiên. Tôi đoán bạn có thể sử dụng dấu ngoặc kép và thoát khỏi dấu ngoặc kép trong JSON <div data-object="{\"hello\":\"world\"}"></div>. Nếu bạn không muốn sử dụng JSON hợp lệ trong thuộc tính, thì bạn sẽ phải tạo định dạng của riêng mình và tự phân tích nó.
Tên lửa Hazmat

Câu trả lời:


181

Nếu chuỗi là từ một nguồn đáng tin cậy , bạn có thể sử dụng evalsau đó JSON.stringifykết quả. Như thế này:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
var json = JSON.stringify(eval("(" + str + ")"));

Lưu ý rằng khi bạn eval là một đối tượng theo nghĩa đen, nó phải được gói trong ngoặc đơn, nếu không, dấu ngoặc nhọn được phân tách thành một khối thay vì một đối tượng.

Tôi cũng đồng ý với các ý kiến ​​dưới câu hỏi rằng sẽ tốt hơn nhiều nếu chỉ mã hóa đối tượng trong JSON hợp lệ để bắt đầu và tránh phải phân tích cú pháp, mã hóa, sau đó có thể phân tích lại nó . HTML hỗ trợ các thuộc tính trích dẫn đơn (chỉ cần đảm bảo mã hóa HTML bất kỳ dấu ngoặc đơn nào bên trong chuỗi).


điều này không có nghĩa gì, nếu chuỗi là từ nguồn đáng tin cậy, tại sao chúng tôi chuyển đổi nó thay vì chúng tôi làm cho nó là json hợp lệ.
allenhwkim

2
@allenhwkim Ý tưởng là chuyển đổi từ JSON không hợp lệ thành JSON hợp lệ, do đó evalchuyển đổi chuỗi thành đối tượng JavaScript (hoạt động, miễn là chuỗi đại diện cho JavaScript hợp lệ, ngay cả khi đó không phải là JSON hợp lệ). Sau đó JSON.stringifychuyển đổi từ một đối tượng trở lại chuỗi JSON (hợp lệ). Gọi evallà nguy hiểm nếu chuỗi không phải từ một nguồn đáng tin cậy bởi vì nó có thể chạy bất kỳ JavaScript nào theo nghĩa đen sẽ mở ra khả năng tấn công kịch bản chéo trang.
Matthew Crumley

2
eval vẫn sẽ làm điều xấu trong trường hợp này nếu chuỗi được xây dựng, ví dụ như thế này: var str = "(function () {console.log (\" bad \ ")}) ()";
Rondo

Sử dụng eval () sẽ thực thi mã JS. Nó có thể dễ dàng bị lạm dụng.
FisNaN

@allenhwkim: chúng tôi không bao giờ tin bất kỳ nguồn nào. Tin tưởng vào CNTT có nghĩa là kiểm tra, kiểm tra và kiểm tra lại.
Laszlo Varga

110

Chuỗi của bạn không hợp lệ JSON, vì vậy JSON.parse(hoặc jQuery$.parseJSON ) sẽ không hoạt động.

Một cách sẽ là sử dụng evalđể "phân tích" JSON "không hợp lệ" và sau đó stringifynó để "chuyển đổi" nó thành JSON hợp lệ.

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }"
str = JSON.stringify(eval('('+str+')'));

Tôi đề nghị thay vì cố gắng "sửa" JSON không hợp lệ của bạn, bạn hãy bắt đầu với JSON hợp lệ ở vị trí đầu tiên. Làm thế nào strđược tạo ra, nó nên được sửa ở đó, trước khi nó được tạo ra, không phải sau đó.

EDIT : Bạn đã nói (trong các bình luận) chuỗi này được lưu trữ trong một thuộc tính dữ liệu:

<div data-object="{hello:'world'}"></div>

Tôi đề nghị bạn sửa nó ở đây, vì vậy nó chỉ có thể là JSON.parsed. Đầu tiên, cả khóa và giá trị của chúng cần được trích dẫn trong dấu ngoặc kép. Nó trông giống như (các thuộc tính được trích dẫn trong HTML là hợp lệ):

<div data-object='{"hello":"world"}'></div>

Bây giờ, bạn chỉ có thể sử dụng JSON.parse(hoặc jQuery $.parseJSON).

var str = '{"hello":"world"}';
var obj = JSON.parse(str);

49

jQuery.parseJSON

str = jQuery.parseJSON(str)

Biên tập. Điều này được cung cấp cho bạn có một chuỗi JSON hợp lệ


1
đúng Tôi đã thấy câu hỏi là làm thế nào để chuyển đổi chuỗi JSON thành đối tượng
Nông dân

43

Sử dụng mã đơn giản trong liên kết dưới đây:

http://msdn.microsoft.com/es-es/l Library /ie / cc836466% 28v = vs.94% 29.aspx

var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
var contact = JSON.parse(jsontext);

và đảo ngược

var str = JSON.stringify(arr);

Chuyển đổi jsontext thành một đối tượng String thông qua String mới (jsontext) có lẽ còn tốt hơn, vì sự an toàn của kiểu.
Phân tích mờ

@fuzzyanalysis: Không, không nên sử dụng trình bao bọc nguyên thủy.
Ry-

1
JSON.parse () phải là câu trả lời được chấp nhận ở đây như được nêu bởi @LouiseMcMahon
pixel 67

24

Tôi hy vọng hàm nhỏ này chuyển đổi chuỗi JSON không hợp lệ thành chuỗi hợp lệ.

function JSONize(str) {
  return str
    // wrap keys without quote with valid double quote
    .replace(/([\$\w]+)\s*:/g, function(_, $1){return '"'+$1+'":'})    
    // replacing single quote wrapped ones to double quote 
    .replace(/'([^']+)'/g, function(_, $1){return '"'+$1+'"'})         
}

Kết quả

var invalidJSON = "{ hello: 'world',foo:1,  bar  : '2', foo1: 1, _bar : 2, $2: 3, 'xxx': 5, \"fuz\": 4, places: ['Africa', 'America', 'Asia', 'Australia'] }"
JSON.parse(invalidJSON) 
//Result: Uncaught SyntaxError: Unexpected token h VM1058:2
JSON.parse(JSONize(invalidJSON)) 
//Result: Object {hello: "world", foo: 1, bar: "2", foo1: 1, _bar: 2…}

Chúng tôi đang cố gắng khử giá trị b bằng cách sử dụng JSON.parse mã của chúng tôi và đây có vẻ là một giải pháp tốt. Chúng tôi vẫn sẽ phải xử lý thay thế liên tục bằng tay, nhưng ít nhất điều này cho phép chứa những trường hợp đó.
ravemir

1
Nó gần như hoàn hảo. Không hoạt động khi : ở một trong các giá trị.
chọn

9

Sử dụng thận trọng (vì eval()):

function strToJson(str) {
  eval("var x = " + str + ";");
  return JSON.stringify(x);
}

gọi là:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
alert( strToJson(str) );

3
Để cử tri xuống vô danh. Tôi thách thức bạn để cung cấp một giải pháp tốt hơn. Ngoài ra, một lý do cho việc bỏ phiếu sẽ tốt đẹp.
Tomalak

1
@Rocket: Bạn sai rồi. a) eval()là cách duy nhất để làm điều đó. b) Tôi cảnh báo OP về nó. c) Nhìn vào câu trả lời của Matthew Crumley và nghĩ về một lời giải thích tốt hơn. (Ồ, và d) tuyên bố eval()là xấu là vô nghĩa trong hình thức tổng quát này.)
Tomalak

2
@Rocket: Ah, hiểu lầm ngay đó. Xin lỗi, tôi nghĩ rằng phiếu bầu là của bạn. :)
Tomalak

1
@ kuboslav: Nó hoạt động tốt, thậm chí bạn đã kiểm tra nó? Anh ấy đang làm điều eval("var x = " + str + ";")đó hoàn toàn hợp lệ. Bạn không cần phải làm var x = ({a:12}).
Tên lửa Hazmat

2
@kuboslav Nó không hoạt động trong IE7 vì IE7 không có hỗ trợ JSON gốc. Nó sẽ bắt đầu hoạt động ngay khi bạn sử dụng json2.js. Đừng quá kích hoạt.
Tomalak

4

Tuyên bố miễn trừ trách nhiệm: không thử điều này ở nhà hoặc cho bất kỳ điều gì yêu cầu các nhà phát triển khác coi trọng bạn:

JSON.stringify(eval('(' + str + ')'));

Ở đó, tôi đã làm nó.
Cố gắng đừng làm điều đó, eval là BAD cho bạn. Như đã nói ở trên, hãy sử dụng JSON shim của Crockford cho các trình duyệt cũ hơn (IE7 trở xuống)

Phương pháp này yêu cầu chuỗi của bạn phải là javascript hợp lệ , sẽ được chuyển đổi thành đối tượng javascript sau đó có thể được tuần tự hóa thành JSON.

chỉnh sửa: cố định như Rocket đề xuất.


Đáng lẽ ra JSON.stringify(eval('('+str+')'));, không phải tôi tha thứ eval, nhưng chuỗi của anh ta không phải là JSON hợp lệ nên JSON.parsekhông hoạt động.
Tên lửa Hazmat

4

Tôi đặt câu trả lời của tôi cho một người quan tâm đến chủ đề cũ này.

Tôi đã tạo ra HTML5 đĩa dữ liệu * phân tích cú pháp cho jQuery plugin và bản demo mà chuyển đổi một chuỗi JSON bị thay đổi thành một đối tượng JavaScript mà không sử dụng eval().

Nó có thể vượt qua các thuộc tính dữ liệu HTML5 * * dưới đây:

<div data-object='{"hello":"world"}'></div>
<div data-object="{hello:'world'}"></div>
<div data-object="hello:world"></div>

vào đối tượng:

{
    hello: "world"
}


2

Có một cách đơn giản hơn nhiều để thực hiện được kỳ tích này, chỉ cần chiếm đoạt thuộc tính onclick của một phần tử giả để buộc trả về chuỗi của bạn dưới dạng đối tượng JavaScript:

var jsonify = (function(div){
  return function(json){
    div.setAttribute('onclick', 'this.__json__ = ' + json);
    div.click();
    return div.__json__;
  }
})(document.createElement('div'));

// Let's say you had a string like '{ one: 1 }' (malformed, a key without quotes)
// jsonify('{ one: 1 }') will output a good ol' JS object ;)

Đây là bản demo: http://codepen.io/csuwldcat/pen/dfzsu (mở bảng điều khiển của bạn)


2

Bạn cần sử dụng "eval" rồi JSON.opesify rồi JSON.parse cho kết quả.

 var errorString= "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
 var jsonValidString = JSON.stringify(eval("(" + errorString+ ")"));
 var JSONObj=JSON.parse(jsonValidString);

nhập mô tả hình ảnh ở đây


1

Bạn phải viết dấu ngoặc tròn, bởi vì không có chúng evalsẽ coi mã bên trong dấu ngoặc nhọn là khối lệnh.

var i = eval("({ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] })");

1

Đặt cược tốt nhất và an toàn nhất của bạn sẽ là JSON5 - JSON cho con người . Nó được tạo ra đặc biệt cho trường hợp sử dụng đó.

const result = JSON5.parse("{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }");

console.log(JSON.stringify(result));
<script src="https://cdnjs.cloudflare.com/ajax/libs/json5/0.5.1/json5.min.js"></script>


1

Sử dụng Hàm mới () tốt hơn eval, nhưng vẫn chỉ nên được sử dụng với đầu vào an toàn.

const parseJSON = obj => Function('"use strict";return (' + obj + ')')();

console.log(parseJSON("{a:(4-1), b:function(){}, c:new Date()}"))
// outputs: Object { a: 3, b: b(), c: Date 2019-06-05T09:55:11.777Z }

Nguồn: MDN , 2ality


0

Đối với ví dụ đơn giản của bạn ở trên, bạn có thể thực hiện việc này bằng cách sử dụng 2 biểu thức chính quy đơn giản thay thế:

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
str.replace(/(\w+):/g, '"$1":').replace(/'/g, '"');
 => '{ "hello": "world", "places": ["Africa", "America", "Asia", "Australia"] }'

Thông báo trước lớn : Cách tiếp cận ngây thơ này giả định rằng đối tượng không có chuỗi chứa a 'hoặc :ký tự. Ví dụ, tôi không thể nghĩ ra một cách hay để chuyển đổi chuỗi đối tượng sau thành JSON mà không cần sử dụng eval:

"{ hello: 'world', places: [\"America: The Progressive's Nightmare\"] }"

0

Chỉ với những điều kỳ quặc của nó, bạn có thể chuyển đổi chuỗi của mình thông qua babel-standalone

var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";

function toJSON() {
  return {
    visitor: {
      Identifier(path) {
        path.node.name = '"' + path.node.name + '"'
      },
      StringLiteral(path) {
        delete path.node.extra
      }
    }
  }
}
Babel.registerPlugin('toJSON', toJSON);
var parsed = Babel.transform('(' + str + ')', {
  plugins: ['toJSON']
});
var json = parsed.code.slice(1, -2)
console.log(JSON.parse(json))
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>


0

var str = "{xin chào: 'thế giới', địa điểm: ['Châu Phi', 'Châu Mỹ', 'Châu Á', 'Úc']}" var fStr = str .replace (/ ([Az] *) (:) / g, '"$ 1":') .replace (/ '/ g, "\" ")

console.log (JSON.parse (fStr))nhập mô tả hình ảnh ở đây

Xin lỗi tôi đang trên điện thoại của tôi, đây là một pic.


0

Một giải pháp với một regex và không sử dụng eval:

str.replace(/([\s\S]*?)(')(.+?)(')([\s\S]*?)/g, "$1\"$3\"$5")

Điều này tôi tin rằng nên hoạt động cho nhiều dòng và tất cả các lần xuất hiện có thể (/ g cờ) của "chuỗi" trích dẫn đơn được thay thế bằng "chuỗi" trích dẫn kép.


0
var str = "{ hello: 'world', places: ['Africa', 'America', 'Asia', 'Australia'] }";
var json = JSON.stringify(eval("(" + str + ")"));

-1

Có lẽ bạn phải thử điều này:

str = jQuery.parseJSON(str)

Câu hỏi được chỉ định "hoặc jQuery" và đây là giải pháp hoàn hảo nếu bạn có sẵn.
Đô thị
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.