2012-07-18 65 views
21

JSON.stringify(eventObject);Làm thế nào để xâu chuỗi đối tượng sự kiện?

cho:

TypeError: Converting circular structure to JSON


dojox.json.ref.toJson(eventObject);

cho:

TypeError: Accessing selectionEnd on an input element that cannot have a selection.


Có một số thư viện/mã sẵn sàng để sử dụng để hoàn thành nó không?

+0

Bạn đang cố gắng xem cấu trúc để trích xuất một số phương thức nhất định từ đối tượng hoặc mục đích của bạn là muốn 'xâu chuỗi' nó là gì? – RobB

+0

gỡ lỗi PhoneGap - gửi cấu trúc dữ liệu, sự kiện và ngăn xếp dấu vết đến lớp gốc – Tar

Trả lời

14

Bạn sẽ không thể tuần tự hóa đối tượng sự kiện bằng JSON.stringify, vì đối tượng sự kiện chứa tham chiếu đến nút DOM và DOM có tham chiếu vòng tròn khắp nơi (ví dụ: mối quan hệ con/mẹ). Theo mặc định, JSON không thể xử lý những thứ này, vì vậy bạn có một chút may mắn ở đó.

Tôi muốn đề xuất xem How to serialize DOM node to JSON even if there are circular references? có một vài đề xuất về cách sắp xếp một nút DOM. Ngoài ra, các câu hỏi sau đây dường như có thông tin hữu ích:

thư viện JSON khả năng xử lý tài liệu tham khảo Thông tư dường như

Hoặc, bạn có thể xóa tất cả các tham chiếu đến các nút DOM nếu bạn không cần chúng, và sau đó sắp xếp lại đối tượng. Bạn không nên làm điều này sau khi tất cả. Xem @PointedEars bình luận :)

+1

Đối tượng sự kiện là [đối tượng lưu trữ] (http://ecma-international.org/ecma-262/5.1/#sec-4.3.8). [Đừng gây rối với chúng] (http://ecma-international.org/ecma-262/5.1/#sec-8.6.2), chẳng hạn như cố gắng xóa thuộc tính của chúng hoặc gán cho các thuộc tính không được gán đến. – PointedEars

+0

Cảm ơn bạn đã chỉ ra điều đó và cho các liên kết! – fresskoma

+0

Bạn được chào đón. – PointedEars

2

Không chắc nếu nó giúp, nhưng tôi chỉ cần stumbled khi này trong tài liệu Angular JS:

* Nguồn: https://code.angularjs.org/1.5.5/docs/guide/expression#-event-

/* 
* return a copy of an object with only non-object keys 
* we need this to avoid circular references 
*/ 
function simpleKeys (original) { 
    return Object.keys(original).reduce(function (obj, key) { 
    obj[key] = typeof original[key] === 'object' ? '{ ... }' : original[key]; 
    return obj; 
    }, {}); 
} 

Bây giờ bạn có thể làm một cái gì đó như:

JSON.stringify(simpleKeys(eventObject)); 
+0

Khi sử dụng điều này trên một touchevent nó chỉ trả về một phần tử duy nhất '{isTrusted: true}'. –

4

Sử dụng "replacer" chức năng để tránh các lỗi:

JSON.stringify(evt, function(k, v) { 
    if (v instanceof Node) { 
     return 'Node'; 
    } 
    if (v instanceof Window) { 
     return 'Window'; 
    } 
    return v; 
}, ' '); 
1

Tôi đã gặp sự cố tương tự và đã viết trình nối tiếp sự kiện đơn giản với phương thức trợ giúp để xóa thuộc tính đường dẫn của sự kiện.Các cách tiếp cận để giải pháp này để chuyển dữ liệu từ sự kiện này cho một đối tượng serializable:

  • Sao chép qua thuộc tính nguyên thủy
  • Sao chép outerHTML cho các phần tử thuộc tính trong đối tượng sự kiện
  • Tính đường bộ chọn cho thuộc tính đường dẫn (điều này tránh sao chép outerHTML của toàn bộ trang HTML)

// Calculate a string representation of a node's DOM path. 
 
var pathToSelector = function(node) { 
 
    if (!node || !node.outerHTML) { 
 
    return null; 
 
    } 
 

 
    var path; 
 
    while (node.parentElement) { 
 
    var name = node.localName; 
 
    if (!name) break; 
 
    name = name.toLowerCase(); 
 
    var parent = node.parentElement; 
 

 
    var domSiblings = []; 
 

 
    if (parent.children && parent.children.length > 0) { 
 
     for (var i = 0; i < parent.children.length; i++) { 
 
     var sibling = parent.children[i]; 
 
     if (sibling.localName && sibling.localName.toLowerCase) { 
 
      if (sibling.localName.toLowerCase() === name) { 
 
      domSiblings.push(sibling); 
 
      } 
 
     } 
 
     } 
 
    } 
 

 
    if (domSiblings.length > 1) { 
 
     name += ':eq(' + domSiblings.indexOf(node) + ')'; 
 
    } 
 
    path = name + (path ? '>' + path : ''); 
 
    node = parent; 
 
    } 
 

 
    return path; 
 
}; 
 

 
// Generate a JSON version of the event. 
 
var serializeEvent = function(e) { 
 
    if (e) { 
 
    var o = { 
 
     eventName: e.toString(), 
 
     altKey: e.altKey, 
 
     bubbles: e.bubbles, 
 
     button: e.button, 
 
     buttons: e.buttons, 
 
     cancelBubble: e.cancelBubble, 
 
     cancelable: e.cancelable, 
 
     clientX: e.clientX, 
 
     clientY: e.clientY, 
 
     composed: e.composed, 
 
     ctrlKey: e.ctrlKey, 
 
     currentTarget: e.currentTarget ? e.currentTarget.outerHTML : null, 
 
     defaultPrevented: e.defaultPrevented, 
 
     detail: e.detail, 
 
     eventPhase: e.eventPhase, 
 
     fromElement: e.fromElement ? e.fromElement.outerHTML : null, 
 
     isTrusted: e.isTrusted, 
 
     layerX: e.layerX, 
 
     layerY: e.layerY, 
 
     metaKey: e.metaKey, 
 
     movementX: e.movementX, 
 
     movementY: e.movementY, 
 
     offsetX: e.offsetX, 
 
     offsetY: e.offsetY, 
 
     pageX: e.pageX, 
 
     pageY: e.pageY, 
 
     path: pathToSelector(e.path && e.path.length ? e.path[0] : null), 
 
     relatedTarget: e.relatedTarget ? e.relatedTarget.outerHTML : null, 
 
     returnValue: e.returnValue, 
 
     screenX: e.screenX, 
 
     screenY: e.screenY, 
 
     shiftKey: e.shiftKey, 
 
     sourceCapabilities: e.sourceCapabilities ? e.sourceCapabilities.toString() : null, 
 
     target: e.target ? e.target.outerHTML : null, 
 
     timeStamp: e.timeStamp, 
 
     toElement: e.toElement ? e.toElement.outerHTML : null, 
 
     type: e.type, 
 
     view: e.view ? e.view.toString() : null, 
 
     which: e.which, 
 
     x: e.x, 
 
     y: e.y 
 
    }; 
 

 
    console.log(JSON.stringify(o, null, 2)); 
 
    } 
 
}; 
 

 
// Create a mock event for this example 
 
var evt = new MouseEvent("click", { 
 
    bubbles: true, 
 
    cancelable: true, 
 
    view: window 
 
}); 
 
var cb = document.getElementById("clicker"); 
 

 
// Add a click listener 
 
cb.addEventListener("click", serializeEvent); 
 

 
// Fire the event 
 
cb.dispatchEvent(evt);
<div> 
 
    <button id="clicker" /> JSONify my click! 
 
</div>

0

Vì vậy, vấn đề là JSON.stringify dường như được bảo lãnh ngay sau khi nó tìm thấy tham chiếu vòng tròn. Dù sao tôi cũng không quan tâm đến các thuộc tính được tham chiếu vòng tròn. Cách tôi nhận phần còn lại của họ là

var str = "{" 
for (var key in data) { 
    if (JSON.stringify(data[key]) !== "") { 
    str += key + ":" + data[key]) + ","; 
    } 
} 
str += "}" 

Điều này về cơ bản sẽ cung cấp cho bạn phần còn lại của thuộc tính. Để tránh các lỗi JS bạn có thể đặt nếu trong try/catch.

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