Я знаю, как разобрать строку JSON и превратить ее в объект JavaScript. Вы можете использовать JSON.parse()
в современных браузерах (и IE9 +).
Это здорово, но как я могу взять этот объект JavaScript и превратить его в определенный объект JavaScript (то есть с определенным прототипом)?
Например, предположим, у вас есть:
function Foo()
{
this.a = 3;
this.b = 2;
this.test = function() {return this.a*this.b;};
}
var fooObj = new Foo();
alert(fooObj.test() ); //Prints 6
var fooJSON = JSON.parse({"a":4, "b": 3});
//Something to convert fooJSON into a Foo Object
//....... (this is what I am missing)
alert(fooJSON.test() ); //Prints 12
Опять же, мне не интересно, как преобразовать строку JSON в общий объект JavaScript. Я хочу знать, как преобразовать строку JSON в объект "Foo". То есть мой объект теперь должен иметь функцию 'test' и свойства 'a' и 'b'.
ОБНОВЛЕНИЕ После некоторых исследований, я подумал об этом ...
Object.cast = function cast(rawObj, constructor)
{
var obj = new constructor();
for(var i in rawObj)
obj[i] = rawObj[i];
return obj;
}
var fooJSON = Object.cast({"a":4, "b": 3}, Foo);
Будет ли это работать?
ОБНОВЛЕНИЕ Май 2017 : «Современный» способ сделать это - через Object.assign
, но эта функция недоступна в IE 11 или более старых браузерах Android.
Ответы:
Текущие ответы содержат много ручного или библиотечного кода. Это не обязательно.
Используйте
JSON.parse('{"a":1}')
для создания простого объекта.Используйте одну из стандартизированных функций для установки прототипа:
Object.assign(new Foo, { a: 1 })
Object.setPrototypeOf({ a: 1 }, Foo.prototype)
источник
Object.setPrototypeOf(...)
. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…setPrototypeOf
являются дескрипторы свойств.См. Пример ниже (в этом примере используется собственный объект JSON). Мои изменения прокомментированы ЗАГЛАВНЫМИ БУКВАМИ:
источник
for (var prop in obj) {if (obj.hasOwnProperty(prop)) {this[prop] = obj[prop];}}
for (var prop in obj) {if (this.hasOwnProperty(prop)) {this[prop] = obj[prop];}}
. Это предполагает, что вы ожидаете, что сервер заполнит все свойства, IMO также должен выдать, если obj.hasOwnProperty () завершится ошибкой ...Хотите добавить функциональность сериализации / десериализации JSON, верно? Тогда посмотрите на это:
вы хотите добиться этого:
toJson () - нормальный метод.
fromJson () - статический метод.
Реализация :
Использование :
Примечание: Если вы хотите , вы можете изменить все определения свойств , таких как
this.title
,this.author
и т.д. путемvar title
,var author
и т.д. , и добавить к ним добытчиками , чтобы выполнить определение UML.источник
toJson()
метод - независимо от того, имеет ли он отдельные свойства, жестко закодированные или использует для каждого из них - должен будет добавить escape-коды обратной косой черты для некоторых символов, которые могут быть в каждом строковом свойстве. (Например, название книги может иметь кавычки.)JSON.stringify()
вместо того, чтобы писать самому jSon (). Не нужно изобретать велосипед сейчас, когда все современные браузеры его поддерживают.serializable = ['title', 'author', ...]
,JSON.stringify(serializable.reduce((obj, prop) => {...obj, [prop]: this[prop]}, {}))
Сообщение в блоге, которое я нашел полезным: Понимание прототипов JavaScript
Вы можете связываться со свойством __proto__ объекта.
Это позволяет fooJSON наследовать прототип Foo.
Я не думаю, что это работает в IE, хотя ... по крайней мере из того, что я прочитал.
источник
__proto__
давно устарела . Более того, из соображений производительности не рекомендуется изменять внутреннее свойство [[Prototype]] уже созданного объекта (путем установки__proto__
или любым другим способом).[[prototype]]
и это, кажется, не имеет значения в Chrome. В Firefox вызов new медленнее, чем при использовании прототипа, а Object.create - самый быстрый. Я предполагаю, что проблема с FF заключается в том, что первый тест медленнее, чем последний, важен только порядок выполнения. В хроме все работает практически с одинаковой скоростью. Я имею в виду доступ к свойствам и вызов методов. Креатин быстрее с новым, но это не так важно. см: jsperf.com/prototype-change-test-8874874/1 и: jsperf.com/prototype-changed-method-callObject.setPrototypeOf(fooJSON, Foo.prototype)
а не устанавливатьfooJSON.__proto__
... верно?Я что-то упускаю в вопросе или почему еще никто не упомянул
reviver
параметрJSON.parse
с 2011 года?Вот упрощенный код для решения, которое работает: https://jsfiddle.net/Ldr2utrr/
PS: Ваш вопрос сбивает с толку: >> Это здорово, но как я могу взять этот объект JavaScript и превратить его в определенный объект JavaScript (т.е. с определенным прототипом)? противоречит названию, где вы спрашиваете о разборе JSON, но в цитируемом абзаце спрашивается о замене прототипа объекта времени выполнения JS.
источник
Альтернативный подход может быть использование
Object.create
. В качестве первого аргумента вы передаете прототип, а для второго вы передаете карту имен свойств дескрипторам:источник
Мне нравится добавлять необязательный аргумент в конструктор и вызывать
Object.assign(this, obj)
, а затем обрабатывать любые свойства, которые являются объектами или массивами самих объектов:источник
Для полноты, вот простая однострочная строка, с которой я закончил (мне не нужно было проверять не-Foo-свойства):
источник
Я создал пакет под названием json-dry . Он поддерживает (круговые) ссылки, а также экземпляры классов.
Вы должны определить 2 новых метода в вашем классе (
toDry
на прототипе иunDry
в качестве статического метода), зарегистрировать class (Dry.registerClass
) и все готово.источник
Хотя технически это не то, что вам нужно, если вы заранее знаете тип объекта, который хотите обработать, вы можете использовать методы call / apply прототипа вашего известного объекта.
Вы можете изменить это
к этому
источник
Я объединил решения, которые мне удалось найти, и скомпилировал их в универсальное решение, которое может автоматически анализировать пользовательский объект и все его поля рекурсивно, чтобы вы могли использовать методы-прототипы после десериализации.
Одно из предположений заключается в том, что вы определили специальное поле, которое указывает его тип для каждого объекта, к которому вы хотите применить его тип автоматически (
this.__type
в примере).использование:
Функция присваивания типов (она работает рекурсивно для назначения типов любым вложенным объектам; она также перебирает массивы для поиска любых подходящих объектов):
источник
В настоящее время принятый ответ не работает для меня. Вам необходимо правильно использовать Object.assign ():
Вы создаете объекты этого класса нормально:
Если у вас есть строка json, которую вам нужно проанализировать в классе Person, сделайте это так:
источник
Ответы Оливерса очень ясны, но если вы ищете решение в angular js, я написал хороший модуль под названием Angular-jsClass, который облегчает эту задачу: объекты, определенные в литеральной нотации, всегда плохи, когда вы стремитесь к большому проекту. но, говоря о том, что разработчики сталкиваются с проблемой, о которой говорит BMiner, как сериализовать json для прототипа или конструктора нотационных объектов
https://github.com/imalhasaranga/Angular-JSClass
источник