Wiem, jak przeanalizować ciąg JSON i przekształcić go w obiekt JavaScript. Możesz używać JSON.parse()
w nowoczesnych przeglądarkach (i IE9 +).
To świetnie, ale jak mogę wziąć ten obiekt JavaScript i przekształcić go w konkretny obiekt JavaScript (tj. Z pewnym prototypem)?
Na przykład załóżmy, że masz:
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
Ponownie, nie zastanawiam się, jak przekonwertować ciąg JSON na ogólny obiekt JavaScript. Chcę wiedzieć, jak przekonwertować ciąg JSON na obiekt „Foo”. Oznacza to, że mój obiekt powinien teraz mieć funkcję „test” oraz właściwości „a” i „b”.
AKTUALIZACJA Po przeprowadzeniu pewnych badań pomyślałem o tym ...
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);
Czy to będzie działało?
AKTUALIZACJA Maj, 2017 : „Nowoczesnym” sposobem jest użycie Object.assign
, ale ta funkcja nie jest dostępna w IE 11 i starszych przeglądarkach Android.
Odpowiedzi:
Bieżące odpowiedzi zawierają dużo ręcznie rozwijanego lub bibliotecznego kodu. To nie jest konieczne.
Służy
JSON.parse('{"a":1}')
do tworzenia zwykłego obiektu.Użyj jednej ze standardowych funkcji, aby ustawić prototyp:
Object.assign(new Foo, { a: 1 })
Object.setPrototypeOf({ a: 1 }, Foo.prototype)
źródło
Object.setPrototypeOf(...)
. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ ...setPrototypeOf
są deskryptory właściwości.Zobacz przykład poniżej (w tym przykładzie zastosowano natywny obiekt JSON). Moje zmiany są komentowane WIELKIMI LITERAMI:
źródło
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];}}
. Zakłada się, że oczekujesz, że serwer wypełni wszystkie właściwości, IMO powinno również zgłosić, jeśli funkcja obj.hasOwnProperty () zawiedzie ...Czy chcesz dodać funkcję serializacji / deserializacji JSON, prawda? Następnie spójrz na to:
Chcesz to osiągnąć:
toJson () to normalna metoda.
fromJson () jest metodą statyczną.
Wdrażanie :
Zastosowanie :
Uwaga: Jeśli chcesz, możesz zmienić wszystkie definicje własności jak
this.title
,this.author
itp przezvar title
,var author
itp i dodać pobierające im osiągnąć definicji UML.źródło
toJson()
metoda - niezależnie od tego, czy ma zakodowane na stałe indywidualne właściwości, czy używa dla każdego z nich - będzie wymagała dodania kodów ucieczki z ukośnikiem odwrotnym dla niektórych znaków, które mogą znajdować się w każdej właściwości ciągu. (Na przykład tytuł książki może zawierać cudzysłowy).JSON.stringify()
zamiast pisać toJSon () sam. Nie ma potrzeby odkrywania na nowo koła, gdy obsługują go wszystkie nowoczesne przeglądarki.serializable = ['title', 'author', ...]
.JSON.stringify(serializable.reduce((obj, prop) => {...obj, [prop]: this[prop]}, {}))
Post na blogu, który okazał się przydatny: Understanding JavaScript Prototypes
Możesz zadzierać z właściwością __proto__ obiektu.
Dzięki temu fooJSON może odziedziczyć prototyp Foo.
Myślę, że to nie działa w IE, chociaż ... przynajmniej z tego, co przeczytałem.
źródło
__proto__
od dawna jest przestarzały . Ponadto ze względu na wydajność nie zaleca się modyfikowania wewnętrznej właściwości [[Prototyp]] już utworzonego obiektu (poprzez ustawienie__proto__
lub w jakikolwiek inny sposób).[[prototype]]
i wydaje się, że nie ma to znaczenia w Chrome. W Firefoksie wywołanie new jest wolniejsze niż używanie prototypu, a Object.create jest najszybsze. Myślę, że problem z FF polega na tym, że pierwszy test jest wolniejszy niż ostatni, tylko kolejność wykonywania ma znaczenie. W chrome wszystko działa prawie z taką samą prędkością. Mam na myśli dostęp do własności i odwoływanie się do metod. Kreatyna jest szybsza dzięki nowemu, ale to nie jest takie ważne. patrz: jsperf.com/prototype-change-test-8874874/1 oraz: jsperf.com/prototype-changed-method-callObject.setPrototypeOf(fooJSON, Foo.prototype)
zamiast ustawiaćfooJSON.__proto__
... prawda?Czy czegoś mi brakuje w pytaniu lub dlaczego nikt inny nie wspomniał o
reviver
parametrzeJSON.parse
od 2011 roku?Oto uproszczony kod rozwiązania, które działa: https://jsfiddle.net/Ldr2utrr/
PS: Twoje pytanie jest niejasne: >> To świetnie, ale jak mogę wziąć ten obiekt JavaScript i przekształcić go w konkretny obiekt JavaScript (tj. Z pewnym prototypem)? zaprzecza tytułowi, w którym pytasz o parsowanie JSON, ale cytowany akapit pyta o zastąpienie prototypu obiektu wykonawczego JS.
źródło
Można zastosować alternatywne podejście
Object.create
. Jako pierwszy argument przekazujesz prototyp, a jako drugi przekazujesz mapę nazw właściwości do deskryptorów:źródło
Lubię dodawać opcjonalny argument do konstruktora i wywoływać
Object.assign(this, obj)
, a następnie obsługiwać wszelkie właściwości, które są obiektami lub tablicami samych obiektów:źródło
Ze względu na kompletność, oto prosty, jednoliniowy tekst, z którym skończyłem (nie musiałem sprawdzać, czy nie ma właściwości innych niż Foo):
źródło
Utworzyłem pakiet o nazwie json-dry . Obsługuje (cykliczne) odwołania, a także instancje klas.
Musisz zdefiniować 2 nowe metody w swojej klasie (
toDry
w prototypie iunDry
jako metoda statyczna), zarejestrować klasę (Dry.registerClass
) i gotowe.źródło
Chociaż technicznie nie jest to to, czego chcesz, jeśli wiesz wcześniej, jaki typ obiektu chcesz obsługiwać, możesz użyć metod call / apply prototypu znanego obiektu.
możesz to zmienić
do tego
źródło
Połączyłem rozwiązania, które udało mi się znaleźć, i skompilowałem je w ogólne, które może automatycznie analizować obiekt niestandardowy i wszystkie jego pola rekurencyjnie, dzięki czemu można używać metod prototypowych po deserializacji.
Jednym z założeń jest to, że zdefiniowałeś specjalne pole, które wskazuje jego typ w każdym obiekcie, który chcesz zastosować automatycznie (
this.__type
w przykładzie).stosowanie:
Funkcja przypisania typu (działa rekurencyjnie, aby przypisać typy do dowolnych zagnieżdżonych obiektów; iteruje również po tablicach, aby znaleźć odpowiednie obiekty):
źródło
Aktualnie zaakceptowana odpowiedź nie działa dla mnie. Musisz poprawnie użyć Object. assign ():
Zwykle tworzysz obiekty tej klasy:
Jeśli masz ciąg json, który musisz przeanalizować w klasie Person, zrób to w następujący sposób:
źródło
Odpowiedzi Olivera są bardzo jasne, ale jeśli szukasz rozwiązania w angular js, napisałem fajny moduł o nazwie Angular-jsClass, który robi to łatwo, posiadanie obiektów zdefiniowanych w notacji litaralnej jest zawsze złe, gdy masz na celu duży projekt ale mówiąc, że programiści mają problem, który dokładnie powiedział BMiner, jak serializować json do prototypu lub konstruktora obiektów notacji
https://github.com/imalhasaranga/Angular-JSClass
źródło