1 (изменено: Rumata, 2021-02-22 03:26:37)

Тема: JS: забавный способ работы с JSON

На форуме DosTips увидел прикольный способ работы с JSON:


var html = new ActiveXObject('HTMLFile');
html.open();
html.write('<html><head><meta http-equiv="x-ua-compatible" content="IE=9" /></head></html>');
html.close();

var JSON = html.parentWindow.JSON;

var obj = {
	a: {
		b: 42,
		c: [ 1, 2, 3 ]
	}
};

var str = JSON.stringify(obj);
// {"a":{"b":42,"c":{"0":1,"1":2,"2":3,"hasOwnProperty":{},"length":3},"hasOwnProperty":{}},"hasOwnProperty":{}}

var obj2 = JSON.parse(str);
// [ActiveXObject]

Все бы хорошо, но все объекты типа ActiveXObject, что значит, что объекты (массивы в том числе) можно только перебрать в циклах for и for in. При переборе циклом for in "вылезают" "лишние" свойства, которые обычно не выводятся: length у массивов и hasOwnProperty у всех объектов. А еще у массивов отсутствуют собственные методы. То есть нельзя, например, вызвать obj2.a.c.join('-').

( 2 * b ) || ! ( 2 * b )

2 (изменено: Xameleon, 2021-02-24 19:43:43)

Re: JS: забавный способ работы с JSON

Rumata пишет:

На форуме DosTips увидел прикольный способ работы с JSON:

У нас на форуме он уже давно гуляет в темах. )

Rumata пишет:

Все бы хорошо, но все объекты типа ActiveXObject, что значит, что объекты (массивы в том числе)

Почему уверенность, что именно "типа ActiveXObject". Я бы сказал, что просто как Object

Да, есть такая проблемка. Причина понятна. Для движка JS массивы являются объектами. Но отличать массивы от объектов он может только в пределах себя. Т.е если массив создан внутри движка, то проблем нет. Собственно именно по этой же причине и происходит появление "лишних" элементов в массиве, которые являются методами.

Я фиксил так:


var document = new ActiveXObject('htmlfile');
document.write('<meta http-equiv="x-ua-compatible" content="IE=Edge">');
var JScript = document.Script,
	JSON = JScript.JSON;

var obj = {
	a: {
		b: 42,
		c: new JScript.Array(1, 2, 3)
	}
};

WSH.Echo(obj.a.c.join(';'));

obj = JSON.stringify(obj,null,'\t');

WSH.Echo(obj)

Возможно JSman сможет нам что-то подсказать.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

3

Re: JS: забавный способ работы с JSON

Xameleon пишет:

типа ActiveXObject

Неточно выразился. Правильнее будет сказать, "экземпляр типа ActiveXObject". Хотя и эта формулировка спорная. Все дело в new ActiveXObject('htmlfile'), который и порождает объект. Если посмотреть на него с этой стороны, то html instanceof ActiveXObject == true. Ну и отсюда все остальное вытекает: все вложенные объекты тоже порождены от ActiveXObject.

( 2 * b ) || ! ( 2 * b )

4 (изменено: Xameleon, 2021-02-24 22:35:37)

Re: JS: забавный способ работы с JSON

Rumata, понял. Согласен.

Немного подумал. В принципе, можно сделать такой фикс, наверное ? Я JS плохо знаю. Наверняка можно грамотнее решить, но пока только такой вариант пришёл в голову.


var JSON = (function(){
	var document = new ActiveXObject('htmlfile');
	document.write('<meta http-equiv="x-ua-compatible" content="IE=Edge">');
	var JScript = document.Script,
		JSON = JScript.JSON;
	
	function patch(object){
		for(var i in object){
			if(typeof object[i] == 'object'){
				if(object[i] instanceof Array) {
					var array = new JScript.Array();
					array.push.apply(array,object[i]);
					object[i] = array;
				}
				patch(object[i]);
			}
		}
		return object
	}
		
	return {
		stringify:function(value, replacer, space){
			try {
				if(typeof value === 'object') value = patch(value);
				return JSON.stringify(value, replacer, space);
			} catch(e){}
			throw new Error(e.description);
		},
		parse:function(text, reviver){
			try {
				return JSON.parse(text, reviver);
			} catch(e){}
			throw new Error(e.description);
		}
	}
})();

var obj = {
	a: {
		b: 42,
		c: [1, 2, 3],
		d: [
			{
				a:1,
				b:[{
					e:1
				}]
			}
		]
	}
};

obj = JSON.stringify(obj,null,'\t');

WSH.Echo(obj);

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

5 (изменено: Xameleon, 2021-02-25 03:01:47)

Re: JS: забавный способ работы с JSON

Rumata, такой вариант подошёл ? Есть предложения как упростить улучшить ?

UPD: Подумал ещё. Можно проще:


var JSON = (function(){
	var document = new ActiveXObject('htmlfile');
	document.write('<meta http-equiv="x-ua-compatible" content="IE=Edge">');
	var JScript = document.Script, JSON = JScript.JSON;
	if(!JSON) throw new Error('Failed to load JSON object.');
	Array.prototype.toJSON = new JScript.Function("return Array.apply(null,this)");
	return {
		stringify:function(){
			try {
				return JSON.stringify.apply(null,arguments);
			} catch(e){}
			throw new Error(e.description);
		},
		parse:function(){
			try {
				return JSON.parse.apply(null,arguments);
			} catch(e){}
			throw new Error(e.description);
		}
	}
})();

var obj = {
	a: {
		b: 42,
		c: [1, 2, 3],
		d: [
			{
				a:1,
				b:[{
					e:1
				}]
			}
		]
	}
};

obj = JSON.stringify(obj,null,'\t');

WSH.Echo(obj);

Но ещё надо бы "запилить" фикс на replacer и reviver, но..... пока чёт лень как-то. Пускай ещё кто-нибудь покреативит.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

6

Re: JS: забавный способ работы с JSON

Я попробовал оба Ваших примера с JSON. Получается интересное решение. Надо будет как-нибудь помедитировать над ними.
Но особо не надо -- ведь есть json2.js, достаточно надежный и, по возможности, максимально приближенный к нативной реализации.

( 2 * b ) || ! ( 2 * b )

7

Re: JS: забавный способ работы с JSON

Rumata пишет:

ведь есть json2.js, достаточно надежный и, по возможности, максимально приближенный к нативной реализации

Полностью согласен.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !