Mam duży obiekt, który chcę przekonwertować na JSON i wysłać. Ma jednak kołową strukturę. Chcę podrzucić dowolne okrągłe odniesienia i wysłać wszystko, co można skreślić. Jak mogę to zrobić?
Dzięki.
var obj = {
a: "foo",
b: obj
}
Chcę zawęzić obiekt obj do:
{"a":"foo"}
javascript
json
node.js
Złupić
źródło
źródło
Odpowiedzi:
Używaj
JSON.stringify
z niestandardowym zamiennikiem. Na przykład:Zamiennik w tym przykładzie nie jest w 100% poprawny (w zależności od definicji „duplikatu”). W następującym przypadku wartość jest odrzucana:
Ale koncepcja jest następująca: użyj niestandardowego zamiennika i śledź przeanalizowane wartości obiektu.
Jako funkcja narzędzia napisana w es6:
źródło
Node.prototype.toJSON = function() { return 'whatever you think that is right'; };
(jeśli chcesz czegoś bardziej ogólnego / specyficznego, po prostu wypróbuj coś w drzewie prototypów: HTMLDivElement implementuje implementację HTMLElement Element implementuje Węzeł implementuje EventTarget; uwaga: może to być zależne od przeglądarki, poprzednie drzewo jest prawdziwe dla Chrome)var a={id:1}; JSON.stringify([a,a]);
cache
będzie nieosiągalny developer.mozilla.org/en-US/docs/Web/JavaScript/…W Node.js możesz użyć util.inspect (obiekt) . Automatycznie zamienia okrągłe linki na „[Circular]”.
Chociaż jest wbudowany (instalacja nie jest wymagana) , musisz go zaimportować
Aby z niego skorzystać, wystarczy zadzwonićPamiętaj również, że możesz przekazać obiekt opcji do sprawdzenia (patrz link powyżej)
Proszę przeczytać i wyrazić uznanie dla komentujących poniżej ...
źródło
var util = require('util');
obj_str = util.inspect(thing)
NIE <s>garbage_str = JSON.stringify(util.inspect(thing))
</s>Zastanawiam się, dlaczego nikt jeszcze nie opublikował właściwego rozwiązania ze strony MDN ...
Widziane wartości powinny być przechowywane w zestawie , a nie w tablicy (zamiennik jest wywoływany na każdym elemencie ) i nie ma potrzeby próbowania
JSON.stringify
każdego elementu w łańcuchu, co prowadzi do odwołania cyklicznego.Podobnie jak w zaakceptowanej odpowiedzi, to rozwiązanie usuwa wszystkie powtarzające się wartości , nie tylko okrągłe. Ale przynajmniej nie ma wykładniczej złożoności.
źródło
replacer = () => { const seen = new WeakSet(); return (key, value) => { if (typeof value === "object" && value !== null) { if (seen.has(value)) { return; } seen.add(value); } return value; }; } () => { const seen = new WeakSet(); return (key, value) => { if (typeof value === "object" && value !== null) { if (seen.has(value)) { return; } seen.add(value); … JSON.stringify({a:1, b: '2'}, replacer)
powracaundefined
w chromiepo prostu zrób
następnie w pliku js
https://github.com/WebReflection/circular-json
UWAGA: Nie mam nic wspólnego z tym pakietem. Ale używam tego do tego.
Aktualizacja 2020
Uwaga: CircularJSON jest w trakcie konserwacji, a jego następca jest spłaszczony .
źródło
JSON
Zasadniczo nadpisywanie nie jest świetne .Flatted.stringify({blah: 1})
wyniki w[{"blah":1}]
) Widzę, że ktoś próbował poruszyć problem na ten temat, a autor skrytykował go i zablokował problem w komentarzach.Naprawdę podobało mi się rozwiązanie Trindaz - bardziej szczegółowe, jednak zawierało pewne błędy. Naprawiłem je dla każdego, kto to lubi.
Dodatkowo dodałem limit długości do moich obiektów pamięci podręcznej.
Jeśli obiekt, który drukuję, jest naprawdę duży - mam na myśli nieskończenie duży - chcę ograniczyć mój algorytm.
źródło
@ Odpowiedź RobW jest poprawna, ale jest bardziej wydajna! Ponieważ używa skrótu / zestawu:
źródło
{"a":{"b":{"a":"d"}}}
a nawet usuwa węzły z pustym obiektem {}Zauważ, że istnieje także
JSON.decycle
metoda wdrożona przez Douglasa Crockforda. Zobacz jego cycle.js . Pozwala to na utworzenie łańcucha dowolnej niemal standardowej struktury:Możesz także odtworzyć oryginalny obiekt za pomocą
retrocycle
metody. Dzięki temu nie musisz usuwać cykli z obiektów, aby je skreślić.Nie zadziała to jednak w przypadku węzłów DOM (które są typową przyczyną cykli w rzeczywistych przypadkach użycia). Na przykład spowoduje to rzucenie:
Zrobiłem rozwidlenie, aby rozwiązać ten problem (zobacz mój rozwidlenie cycle.js ). To powinno działać dobrze:
Zauważ, że w moim rozwidleniu
JSON.decycle(variable)
działa jak w oryginale i zgłosi wyjątek, gdyvariable
zawierają węzły / elementy DOM.Podczas korzystania
JSON.decycle(variable, true)
akceptujesz fakt, że wynik nie będzie odwracalny (retrocycle nie odtworzy węzłów DOM). Elementy DOM powinny być jednak do pewnego stopnia identyfikowalne. Na przykład, jeślidiv
element ma identyfikator, zostanie zastąpiony łańcuchem"div#id-of-the-element"
.źródło
JSON.decycle(a, true)
co się stanie, gdy przekażesz true jako parametr w celu wyłączenia funkcjistringifyNodes
opcja jest prawdziwa w rozwidleniu. Będzie to zrzucić na przykładdiv
z id = "some-id" ciąg:div#some-id
. Unikniesz pewnych problemów, ale nie będziesz w stanie w pełni przełączyć się na cykl.Polecam sprawdzenie json-stringify-safe from @ isaacs-- jest używany w NPM.
Żeby zainstalować:
Używać:
Daje to:
źródło
Dla przyszłych pracowników szukających rozwiązania tego problemu, gdy nie znasz kluczy wszystkich odwołań cyklicznych, możesz użyć opakowania wokół funkcji JSON.stringify, aby wykluczyć odwołania cykliczne. Zobacz przykładowy skrypt na https://gist.github.com/4653128 .
Rozwiązanie zasadniczo sprowadza się do zachowania odniesienia do uprzednio wydrukowanych obiektów w tablicy i sprawdzenia tego w funkcji zastępującej przed zwróceniem wartości. Jest to bardziej restrykcyjne niż wykluczanie okrągłych odniesień, ponieważ wyklucza również dwukrotne drukowanie obiektu, którego jednym z bocznych skutków jest unikanie okrągłych odniesień.
Przykładowe opakowanie:
źródło
if(printedObjIndex)
podczas pisania,if(printedObjIndex==false)
ponieważindex
można go również0
przetłumaczyć,false
chyba że wyraźnie postanowisz inaczej.===
?0 == false
jesttrue
,0 === false
jestfalse
. ; ^) Ale wolałbym nie inicjowaćprintedObjIndex
na fałsz, ponieważ wtedy możesz się temu przeciwstawićundefined
, abyś (no cóż, Trindaza) nie mieszał metafor w dziwny sposób.Użyj metody JSON.stringify z zamiennikiem. Przeczytaj tę dokumentację, aby uzyskać więcej informacji. http://msdn.microsoft.com/en-us/library/cc836459%28v=vs.94%29.aspx
Wymyśl sposób na zapełnienie tablicy zastępczej cyklicznymi odwołaniami. Możesz użyć metody typeof, aby sprawdzić, czy właściwość jest typu „obiekt” (referencja), a także dokładną kontrolę równości (===), aby zweryfikować referencję cykliczną.
źródło
var obj = {foo:obj}
nie nie tworzyć odwołanie cykliczne. Zamiast tego tworzy obiekt, któregofoo
atrybut odwołuje się do poprzedniej wartościobj
(undefined
jeśli nie został wcześniej zdefiniowany, zadeklarowany z powoduvar obj
).Gdyby
skutkuje
Następnie możesz wydrukować w ten sposób:
źródło
ocenia:
z funkcją:
źródło
Wiem, że to stare pytanie, ale chciałbym zasugerować utworzony przez siebie pakiet NPM o nazwie smart-circular , który działa inaczej niż inne proponowane sposoby. Jest to szczególnie przydatne, jeśli używasz dużych i głębokich obiektów .
Niektóre funkcje to:
Zastępowanie okrągłych odniesień lub po prostu powtarzanych struktur wewnątrz obiektu ścieżką prowadzącą do jego pierwszego wystąpienia (nie tylko ciąg [kołowy] );
Poszukując kolistości przy pierwszym wyszukiwaniu, pakiet zapewnia, że ta ścieżka jest tak mała, jak to możliwe, co jest ważne, gdy mamy do czynienia z bardzo dużymi i głębokimi obiektami, gdzie ścieżki mogą stać się denerwująco długie i trudne do podążenia (niestandardowe zastąpienie w JSON.stringify robi DFS);
Umożliwia spersonalizowane zamiany, przydatne w celu uproszczenia lub zignorowania mniej ważnych części obiektu;
Wreszcie ścieżki są zapisywane dokładnie w sposób niezbędny do uzyskania dostępu do pola, do którego istnieje odwołanie, co może pomóc w debugowaniu.
źródło
Drugi argument JSON.stringify () również pozwala określić tablicę nazw kluczy, które powinny być zachowane od każdego obiektu, który napotka w danych. Może to nie działać we wszystkich przypadkach użycia, ale jest znacznie prostszym rozwiązaniem.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
Uwaga: Co dziwne, definicja obiektu z OP nie rzuca okrągłego błędu odniesienia w najnowszym Chrome lub Firefox. Definicja zawarta w tej odpowiedzi została zmodyfikowana tak, aby nie rzucać się błąd.
źródło
Aby zaktualizować odpowiedź przesłaniania sposobu działania JSON (prawdopodobnie nie jest to zalecane, ale bardzo proste), nie używaj
circular-json
(jest przestarzałe). Zamiast tego użyj następcy spłaszczonego:https://www.npmjs.com/package/flatted
Zapożyczono ze starej odpowiedzi powyżej od @ user1541685, ale zastąpiono nową:
npm i --save flatted
następnie w pliku js
źródło
Znalazłem bibliotekę circular-json na githubie i działała dobrze dla mojego problemu.
Kilka dobrych funkcji, które uznałem za przydatne:
źródło
Rozwiązuję ten problem w następujący sposób:
źródło
_class: ClassName { data: "here" }
, więc dodałem następującą zasadę.replace(/(\w+) {/g, '{ __ClassName__: "$1", ')
. W moim przypadku próbowałem zobaczyć, jak wyglądał obiekt żądania HTTP.Wiem, że to pytanie jest stare i ma wiele świetnych odpowiedzi, ale zamieszczam tę odpowiedź z powodu jej nowego smaku (es5 +)
Pokaż fragment kodu
źródło
Chociaż odpowiedź na to pytanie jest wystarczająca, można również jawnie usunąć daną właściwość przed powiązaniem za pomocą
delete
operatora.usuń operatora
usunie to potrzebę budowania lub utrzymywania złożonej logiki w celu usunięcia odwołań cyklicznych.
źródło
źródło
innym rozwiązaniem tego problemu z tego rodzaju obiektami jest użycie tej biblioteki
https://github.com/ericmuyser/stringy
jest to proste i można to w kilku prostych krokach rozwiązać.
źródło
Na podstawie innych odpowiedzi otrzymuję następujący kod. Działa całkiem dobrze z referencjami kołowymi, obiektami z niestandardowymi konstruktorami.
Z danego obiektu do serializacji,
Github Link - DecycledJSON
Przykład użycia 1:
Przykład użycia 2:
źródło
Spróbuj tego:
źródło
seen.push(value)
= -D? Jakfor (var key in value) {value[key] = circular_replacer(value[key]);}
W moim rozwiązaniu, jeśli natrafisz na cykl, nie mówi on po prostu „cykl” (lub nic), mówi coś w rodzaju foo: patrz obiekt nr 42 powyżej i aby zobaczyć, gdzie foo wskazuje, możesz przewijać i wyszukiwać dla obiektu nr 42 (każdy obiekt, gdy się uruchamia, mówi obiekt nr xxx z jakąś liczbą całkowitą xxx)
Skrawek:
źródło