การยกเลิกการทำให้ JSON เป็นวัตถุ JavaScript


266

ฉันมีสตริงในแอปพลิเคชันเซิร์ฟเวอร์ Java ที่เข้าถึงได้โดยใช้ AJAX ดูเหมือนสิ่งต่อไปนี้:

var json = [{
    "adjacencies": [
        {
          "nodeTo": "graphnode2",
          "nodeFrom": "graphnode1",
          "data": {
            "$color": "#557EAA"
          }
        }
    ],
    "data": {
      "$color": "#EBB056",
      "$type": "triangle",
      "$dim": 9
    },
    "id": "graphnode1",
    "name": "graphnode1"
},{
    "adjacencies": [],
    "data": {
      "$color": "#EBB056",
      "$type": "triangle",
      "$dim": 9
    },
    "id": "graphnode2",
    "name": "graphnode2"
}];

เมื่อสตริงถูกดึงออกจากเซิร์ฟเวอร์มีวิธีง่าย ๆ ในการเปลี่ยนให้เป็นวัตถุ JavaScript ที่มีชีวิต (หรืออาร์เรย์) หรือไม่? หรือฉันจะต้องแบ่งสตริงด้วยตนเองและสร้างวัตถุของฉันด้วยตนเอง?


อาจเป็นไปได้ซ้ำกับวิธีแจง json ใน javascript
Felix Kling

คำตอบ:


397

JSON.parse()สนับสนุนเบราว์เซอร์ที่ทันสมัย

var arr_from_json = JSON.parse( json_string );

ในเบราว์เซอร์ที่ทำไม่ได้คุณสามารถรวมห้องสมุดjson2


วิธีนี้จะใช้ได้กับฟิลด์วันที่ใน JSON เช่น {StartDate: "\ / Date (1372575600000) \ /"}?
Philipp Munin

@PhilippMunin คุณสามารถใช้ฟังก์ชัน Date จาก javascript API: new Date (parseInt ("/ Date (946681200000) /". แทนที่ ('/ Date (', '')));
Leo

หรือ Map () วัตถุ ฯลฯ คุณจะทำการdeserialisation ที่เหมาะสมอย่างไร
Ewan

25

จุดทั้งหมดของ JSON คือสตริง JSON สามารถถูกแปลงเป็นวัตถุดั้งเดิมโดยไม่ทำอะไรเลย ตรวจสอบการเชื่อมโยง

คุณสามารถใช้อย่างใดอย่างหนึ่งหรือeval(string)JSON.parse(string)

อย่างไรก็ตามevalมีความเสี่ยง จาก json.org:

ฟังก์ชั่น eval นั้นเร็วมาก อย่างไรก็ตามมันสามารถรวบรวมและรันโปรแกรมจาวาสคริปต์ใด ๆ ดังนั้นจึงอาจมีปัญหาด้านความปลอดภัย การใช้ eval จะถูกระบุเมื่อแหล่งที่เชื่อถือได้และมีความสามารถ การใช้ตัวแยกวิเคราะห์ JSON นั้นปลอดภัยกว่ามาก ในเว็บแอปพลิเคชันผ่าน XMLHttpRequest อนุญาตให้มีการสื่อสารกับแหล่งกำเนิดเดียวกับที่ให้เพจนั้นดังนั้นจึงเชื่อถือได้ แต่มันอาจไม่เก่ง หากเซิร์ฟเวอร์ไม่เข้มงวดในการเข้ารหัส JSON หรือหากไม่ตรวจสอบอินพุตทั้งหมดอย่างละเอียดถี่ถ้วนก็สามารถส่งข้อความ JSON ที่ไม่ถูกต้องซึ่งอาจมีสคริปต์อันตราย ฟังก์ชั่น eval จะรันสคริปต์ปล่อยความอาฆาตพยาบาท


1
ฉันไม่เข้าใจความเสี่ยง ทุกคนไม่สามารถใช้ดีบักเกอร์ js เพื่อแทรกและเรียกใช้สคริปต์ที่ต้องการได้หรือไม่
xr280xr

3
@ xr280xr ใช่ แต่มันเกิดขึ้นเฉพาะภายในเบราว์เซอร์ไม่ใช่ทุกเบราว์เซอร์ที่ดาวน์โหลดเว็บไซต์
masterxilo

16

ชอบ jQuery ไหม! (สาระการเรียนรู้แกนกลาง)

function parseJSON(data) {
    return window.JSON && window.JSON.parse ? window.JSON.parse( data ) : (new Function("return " + data))(); 
}
// testing
obj = parseJSON('{"name":"John"}');
alert(obj.name);

วิธีนี้คุณไม่จำเป็นต้องใช้ไลบรารีภายนอกและยังสามารถใช้งานบนเบราว์เซอร์รุ่นเก่าได้


7
eval()ลักษณะเช่นนี้มันก็กลับไปเทียบเท่ากับการลดลง
LarsH

1
สิ่งนี้เป็นสิ่งที่อันตรายความจริงคือความชั่วร้าย!
caesarsol

8

เพื่อรวบรวมรายการทั้งหมดของอาร์เรย์และส่งคืนวัตถุ json

collectData: function (arrayElements) {

        var main = [];

        for (var i = 0; i < arrayElements.length; i++) {
            var data = {};
            this.e = arrayElements[i];            
            data.text = arrayElements[i].text;
            data.val = arrayElements[i].value;
            main[i] = data;
        }
        return main;
    },

ในการแยกวิเคราะห์ข้อมูลเดียวกันที่เราทำเช่นนี้

dummyParse: function (json) {       
        var o = JSON.parse(json); //conerted the string into JSON object        
        $.each(o, function () {
            inner = this;
            $.each(inner, function (index) {
                alert(this.text)
            });
        });

}

4

คุณยังสามารถใช้eval()แต่JSON.parse()เป็นวิธีที่ปลอดภัยกว่าและง่ายกว่าดังนั้นทำไมคุณจะ

ดีและใช้งานได้

var yourJsonObject = JSON.parse(json_as_text);

evalผมไม่เห็นเหตุผลว่าทำไมคุณต้องการที่จะใช้ มันทำให้ใบสมัครของคุณมีความเสี่ยงเท่านั้น

ที่กล่าวว่า - เป็นไปได้เช่นกัน

ไม่ดี - แต่ยังใช้งานได้

var yourJsonObject = eval(json_as_text);

เหตุใดจึงเป็นevalความคิดที่ไม่ดี

ลองพิจารณาตัวอย่างต่อไปนี้

บุคคลที่สามหรือผู้ใช้บางรายให้ข้อมูลสตริง JSON

var json = `
[{
    "adjacencies": [
        {
          "nodeTo": function(){
            return "delete server files - you have been hacked!";
          }(),
          "nodeFrom": "graphnode1",
          "data": {
            "$color": "#557EAA"
          }
        }
    ],
    "data": {
      "$color": "#EBB056",
      "$type": "triangle",
      "$dim": 9
    },
    "id": "graphnode1",
    "name": "graphnode1"
},{
    "adjacencies": [],
    "data": {
      "$color": "#EBB056",
      "$type": "triangle",
      "$dim": 9
    },
    "id": "graphnode2",
    "name": "graphnode2"
}]
`;

สคริปต์ฝั่งเซิร์ฟเวอร์ของคุณประมวลผลข้อมูลนั้น

การใช้JSON.parse:

window.onload = function(){
  var placeholder = document.getElementById('placeholder1');
  placeholder.innerHTML = JSON.parse(json)[0].adjacencies[0].nodeTo;
}

จะโยน:

Uncaught SyntaxError: Unexpected token u in JSON at position X. 

ฟังก์ชั่นจะไม่ถูกดำเนินการ

คุณปลอดภัย.

การใช้eval():

window.onload = function(){
  var placeholder = document.getElementById('placeholder1');
  placeholder.innerHTML = eval(json)[0].adjacencies[0].nodeTo;
}

จะเรียกใช้ฟังก์ชันและส่งคืนข้อความ

หากฉันแทนที่ฟังก์ชั่นที่ไม่เป็นอันตรายด้วยสิ่งที่ลบไฟล์ออกจากโฟลเดอร์เว็บไซต์ของคุณคุณถูกแฮ็ก ไม่มีข้อผิดพลาด / คำเตือนจะถูกโยนในตัวอย่างนี้

คุณไม่ปลอดภัย

ฉันสามารถจัดการสตริงข้อความ JSON ดังนั้นจึงทำหน้าที่เป็นฟังก์ชันที่จะดำเนินการบนเซิร์ฟเวอร์

eval(JSON)[0].adjacencies[0].nodeTo คาดว่าจะประมวลผลสตริง JSON แต่ในความเป็นจริงเราเพิ่งดำเนินการฟังก์ชั่นบนเซิร์ฟเวอร์ของเรา

สิ่งนี้สามารถป้องกันได้หากเราตรวจสอบข้อมูลจากผู้ใช้ทั้งหมดก่อนที่จะส่งผ่านไปยังeval()ฟังก์ชั่น แต่ทำไมไม่ใช้เครื่องมือในตัวสำหรับการแยกวิเคราะห์ JSON และหลีกเลี่ยงปัญหาและอันตรายทั้งหมด?


1

และถ้าคุณต้องการให้วัตถุที่มีการ deserialised มีฟังก์ชันคุณสามารถใช้เครื่องมือขนาดเล็กของฉัน: https://github.com/khayll/jsmix

//first you'll need to define your model
var GraphNode = function() {};
GraphNode.prototype.getType = function() {
   return this.$type;
}

var Adjacency = function() {};
Adjacency.prototype.getData =n function() {
    return this.data;
}

//then you could say:
var result = JSMix(jsonData)
    .withObject(GraphNode.prototype, "*")
    .withObject(Adjacency.prototype, "*.adjacencies")
    .build();

//and use them
console.log(result[1][0].getData());

0

หากคุณวางสตริงในฝั่งเซิร์ฟเวอร์ลงใน html ไม่จำเป็นต้องทำอะไร:

สำหรับ java ธรรมดาใน jsp:

var jsonObj=<%=jsonStringInJavaServlet%>;

สำหรับ Struts กว้าง jsp:

var jsonObj=<s:property value="jsonStringInJavaServlet" escape="false" escapeHtml="false"/>;

-3

ฉันคิดว่านี่น่าจะช่วยได้:

นอกจากนี้เอกสารยังพิสูจน์ว่าคุณสามารถใช้ require () สำหรับไฟล์ json: https://www.bennadel.com/blog/2908-you-can-use-require-to-load-json-javascript-object-notation-files -in-โหนด js.htm

var jsonfile = require("./path/to/jsonfile.json");
node = jsonfile.adjacencies.nodeTo;
node2 = jsonfile.adjacencies.nodeFrom;
node3 = jsonfile.adjacencies.data.$color;
//other things.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.