Verständnisproblem AJAX-Request verarbeiten
Matze
- javascript
0 Steel0 Matze
0 Cheatah
Hallo und guten Morgen!
Ich setze einen AJAX-Request auf eine PHP-Datei ab. In der PHP-Datei ist eine Datenbankabfrage die 2 Ergebnisse in der Form zurück liefert:
Array ( [0]=>Wert, [1]=>Wert, ...., [35]=>Wert)
Also 2 Datensätze mit 36 Werten.
Diese Datensätze würde ich gern in 2 JavaScript-Arrays schreiben, damit ich nach dem Request die entsprechenden Werte an die dafür vorgesehenen Stellen im HTML schreiben kann.
Jetzt kommt mein Verständnisproblem. Normalerweise schreibe ich JavaScript ja in den Head-Bereich eines HTML-Dokuments. Eventhandler inline.
Wie kann ich die Daten an ein JS-Array übergeben?
Ich möchte zum Schluss so etwas haben
document.getElementById('arr1wert0').innerHTML = Array1[0];
document.getElementById('arr1wert1').innerHTML = Array1[1];
...
document.getElementById('arr1wert35').innerHTML = Array1[35];
document.getElementById('arr2wert0').innerHTML = Array2[0];
document.getElementById('arr2wert1').innerHTML = Array2[1];
...
document.getElementById('arr2wert35').innerHTML = Array2[35];
Wobei man dafür auch eine Schleife schreiben könnte. Nur des Beispiels wegen...
Wie setz ich das um? Denk ich in eine falsche Richtung?
Danke für eure Hilfe!
Grüße, Matze
Hi!
eval() auf den returnwert des php-scripts anwenden.
Guten Morgen Steel!
eval() auf den returnwert des php-scripts anwenden.
Keine andere Lösung? Eval scheint mir meißt etwas "radikal".
Oder ist das für mein Vorhaben gängige Praxis?
Danke und Grüße, Matze
Hi,
Ich setze einen AJAX-Request auf eine PHP-Datei ab. In der PHP-Datei ist eine Datenbankabfrage die 2 Ergebnisse in der Form zurück liefert:
genauer gesagt ist die Rückgabe ein String. Ziemlich genau so sieht JavaScript das auch. Die Folge:
Diese Datensätze würde ich gern in 2 JavaScript-Arrays schreiben,
Du würdest Dich gern mit JSON beschäftigen.
Jetzt kommt mein Verständnisproblem. Normalerweise schreibe ich JavaScript ja in den Head-Bereich eines HTML-Dokuments.
Nun ja, ich habe gelernt, dass "normal" ein ziemlich relativer Begriff ist.
Eventhandler inline.
Im Idealfall nicht.
Cheatah
Hi,
Ich setze einen AJAX-Request auf eine PHP-Datei ab. In der PHP-Datei ist eine Datenbankabfrage die 2 Ergebnisse in der Form zurück liefert:
genauer gesagt ist die Rückgabe ein String. Ziemlich genau so sieht JavaScript das auch. Die Folge:
Diese Datensätze würde ich gern in 2 JavaScript-Arrays schreiben,
Du würdest Dich gern mit JSON beschäftigen.
Mh also ein Array erstellen mit 2 Objekten und je 36 String:Value-Pärchen? Und das dann per eval() ins JS übernehmen?
In etwa so:
mein_array[
object1{
"Element0": "Wert",
...,
"Element35: "Wert"
}
,
object2{
"Element0": "Wert",
...,
"Element35: "Wert"
}
]
Wenn ich jetzt eval() darauf anwende, kann ich dann mein_array[object1][Element0] ansprechen/ausgeben?
Ich hab leider noch nicht mit JSON gearbeitet und wär deshalb für weitere Hilfe dankbar.
Danke und Grüße, Matze
Hallo und guten Abend Cheatah!
Du würdest Dich gern mit JSON beschäftigen.
Ok, das hab ich heut gemacht.
Ich habe also folgendes JSON-Array mit 2 Objekten (sagt man das dann so?)
[
{
"Element0":"Wert1", "Element1":"Wert2", ..., "Element35":"Wert36"
},
{
"Element0":"Wert1", "Element1":"Wert2", ..., "Element35":"Wert36"
}
]
Darauf wende ich an:
var foo = eval('request.responseText');
document.getElementById('test').innerHTML = stats.length;
wobei request.responseText das JSON-Array ist.
Ich dachte die Ausagbe mit .length gibt mir die Anzahl der Elemente des Arrays, es gibt mir aber die Länge des Arrays als String wieder.
Was mache ich da falsch? Ich weiß nicht wie ich das erste und das zweite "Element0" z.B. ausgeben kann. Bzw. halt dessen Wert.
Danke und Grüße, Matze
Ich habe also folgendes JSON-Array mit 2 Objekten (sagt man das dann so?)
JSON ist nur ein Technik. Du hast ein String, den du mit eval in JS umwandeln kannst.
[
{
"Element0":"Wert1", "Element1":"Wert2", ..., "Element35":"Wert36"
},
{
"Element0":"Wert1", "Element1":"Wert2", ..., "Element35":"Wert36"
}
]Darauf wende ich an:
var foo = eval('request.responseText');
document.getElementById('test').innerHTML = stats.length;
>
> wobei request.responseText das JSON-Array ist.
> Ich dachte die Ausagbe mit .length gibt mir die Anzahl der Elemente des Arrays, es gibt mir aber die Länge des Arrays als String wieder.
Kann ich nicht nachvolziehen, wenn ich dein Beipsiel nehme krieg ich die Anzahl der Einträge angezeigt:
~~~javascript
var str = '[{"Element0":"Wert1", "Element1":"Wert2", "Element35":"Wert36"},{"Element0":"Wert1", "Element1":"Wert2", "Element35":"Wert36"}]';
var foo = eval( str);
alert(foo.length);
Was mache ich da falsch? Ich weiß nicht wie ich das erste und das zweite "Element0" z.B. ausgeben kann. Bzw. halt dessen Wert.
Was du falsch machst, weiß ich nicht, aber an die die Elemente kommst du so:
foo[0].Element0;
foo[1].Element0
Struppi.
Hallo Struppi!
Ich dachte die Ausagbe mit .length gibt mir die Anzahl der Elemente des Arrays, es gibt mir aber die Länge des Arrays als String wieder.
Kann ich nicht nachvolziehen, wenn ich dein Beipsiel nehme krieg ich die Anzahl der Einträge angezeigt:
Ich hab ein bisschen gegoogled und auf ein Beispiel in der Form gestoßen.
var foo = eval('(' + request.responseText + ')');
So funktioniert es.
Ich würde jetzt gern wissen warum eval('request.responseText');
nicht als Array "erkannt" wird. Die Syntax bei eval('('+...+')'); ist mir also nicht ganz klar.
Könnte mir das vielleicht jemand erklären?
Danke und Grüße, Matze
So funktioniert es.
Ich würde jetzt gern wissen warumeval('request.responseText');
nicht als Array "erkannt" wird. Die Syntax bei eval('('+...+')'); ist mir also nicht ganz klar.
Mir auch nicht. Mein Beispiel das ich dir gezeigt habe, funktioniert auch ohne die zusätzlichne Klammern. Wenn es mit deinen Daten nicht funktioniert, dann stimmt mit denen irgendetwas nicht.
Struppi.
Ich hab ein bisschen gegoogled und auf ein Beispiel in der Form gestoßen.
var foo = eval('(' + request.responseText + ')');
So funktioniert es.
Ich würde jetzt gern wissen warumeval('request.responseText');
nicht als Array "erkannt" wird. Die Syntax bei eval('('+...+')'); ist mir also nicht ganz klar.Könnte mir das vielleicht jemand erklären?
Ja, es scheint so, dass bei Objektliteralen in JSON eval
bisweilen glaubt, ein Block-Statement vor sich zu haben und dann falsch parst. Die Klammern verhindern das, da dann klar ist, dass ein Ausdruck ausgewertet werden soll.
Es gibt übrigens unter JSON in JavaScript den Verweis auf einen freien (Public Domain) JSON-Parser, den könntest du statt eval
nehmen. Wäre m.E. die sauberere Alternative.
Könnte mir das vielleicht jemand erklären?
Ja, es scheint so, dass bei Objektliteralen in JSONeval
bisweilen glaubt, ein Block-Statement vor sich zu haben und dann falsch parst.
Wann passiert das? Nicht bei seinem Beispiel.
Struppi.
Könnte mir das vielleicht jemand erklären?
Ja, es scheint so, dass bei Objektliteralen in JSONeval
bisweilen glaubt, ein Block-Statement vor sich zu haben und dann falsch parst.Wann passiert das? Nicht bei seinem Beispiel.
var x=eval('{"x":"50"}');
wirft mir Fehler in Opera 9.52 ("Syntax Error"), Firefox 3.0.4 ("Invalid label") und Internet Explorer 6 ("';' expected") aus, var x=eval('({"x":"50"})');
funktioniert tadellos.
Das Problem ist offenbar, dass {
als Start eines Block-Statements aufgefasst wird und "x"
als (invalides) Label.
Könnte mir das vielleicht jemand erklären?
Ja, es scheint so, dass bei Objektliteralen in JSONeval
bisweilen glaubt, ein Block-Statement vor sich zu haben und dann falsch parst.Wann passiert das? Nicht bei seinem Beispiel.
var x=eval('{"x":"50"}');
wirft mir Fehler in Opera 9.52 ("Syntax Error"), Firefox 3.0.4 ("Invalid label") und Internet Explorer 6 ("';' expected") aus,var x=eval('({"x":"50"})');
funktioniert tadellos.
Danke.
Trotzdem ist natürlich das was Matze uns gezeigt hat merkwürdig. Er hatte ein Array und dort funktioniert es ohne die Klammerung:
var x=eval('[{"x":"50"}]');
Mich wunderte, dass er uns Code und einen Fehler zeigt, die ganz offensichtlich in keinem Zusammenhang stehen.
Struppi.
Ich habe also folgendes JSON-Array mit 2 Objekten (sagt man das dann so?)
[
{
"Element0":"Wert1", "Element1":"Wert2", ..., "Element35":"Wert36"
},
{
"Element0":"Wert1", "Element1":"Wert2", ..., "Element35":"Wert36"
}
]Darauf wende ich an:
var foo = eval('request.responseText');
document.getElementById('test').innerHTML = stats.length;
> wobei request.responseText das JSON-Array ist.
Wieso `stats.length`{:.language-javascript}? Was ist denn `stats`{:.language-javascript}?
> Ich dachte die Ausagbe mit .length gibt mir die Anzahl der Elemente des Arrays, es gibt mir aber die Länge des Arrays als String wieder.
Wo kriegst du die Länge des Arrays als String? Kannst du mal ein vollständiges Minimalbeispiel (mit Beispieldaten) verlinken?
> Was mache ich da falsch? Ich weiß nicht wie ich das erste und das zweite "Element0" z.B. ausgeben kann. Bzw. halt dessen Wert.
~~~javascript
var foo=eval('request.responseText'); // request.responseText siehe oben
var erstesElement=foo[0]["Element0"], zweitesElement=foo[1]["Element0"];
Statt "Element0" müsstest du natürlich den passenden String eintragen (in beiden Fällen).
Hallo!
Darauf wende ich an:
var foo = eval('request.responseText');
document.getElementById('test').innerHTML = stats.length;
> > wobei request.responseText das JSON-Array ist.
> Wieso `stats.length`{:.language-javascript}? Was ist denn `stats`{:.language-javascript}?
Sorry der falsche Variablenname hat sich ins Beispiel eingeschlichen, hab ich noch gar nicht bemerkt.
stats === foo
> > Ich dachte die Ausagbe mit .length gibt mir die Anzahl der Elemente des Arrays, es gibt mir aber die Länge des Arrays als String wieder.
> Wo kriegst du die Länge des Arrays als String? Kannst du mal ein vollständiges Minimalbeispiel (mit Beispieldaten) verlinken?
Also mein JSON sieht verkürzt so aus:
[{"WebCamName":"Rockau","Protokoll":"ws444","GPS":"5101'42.05\"Nord 1351'42.83\"Ost","Hoehe":"252"},{"WebCamName":"Loschwitz","Protokoll":"ws2300","GPS":"5103'10.11\"Nord 1349'20.48\"Ost","Hoehe":"190"}]
Mein JavaScript (mit "stats"):
~~~javascript
<script type="text/javascript">
var loop = setInterval('get_stats()', 60000);
function get_stats(){
var request = null;
try{
request = new XMLHttpRequest();
}
catch (ms){
try{
request = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (nonms){
try{
request = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (failed){
request = null;
}
}
}
request.open("GET", 'get_stats.php', true);
request.onreadystatechange = function(){
switch(request.readyState){
case 4:
if(request.status == 200) var stats = eval('('+request.responseText+')'); // Der Teil mit dem eval()
document.getElementById('cam').innerHTML = stats[0].WebCamName;
break;
default:
return false;
break;
}
}
request.send(null);
}
</script>
Und ein Div mit der Id "cam".
Ersetze ich jetzt oben eval('('+request.responseText+')') durch eval('request.responseText')
und document.getElementById('cam').innerHTML = stats[0].WebCamName; durch document.getElementById('cam').innerHTML = stats.length;
erhalte ich nicht wie erwartet 2 sondern eine Zahl im zweitausender Bereich. Ebend die Länge des Strings. stats[0].WebCamName
ergibt dann natürlich auch undefined im FF.
Grüße, Matze
Also mein JSON sieht verkürzt so aus:
[{"WebCamName":"Rockau","Protokoll":"ws444","GPS":"5101'42.05"Nord 1351'42.83"Ost","Hoehe":"252"},{"WebCamName":"Loschwitz","Protokoll":"ws2300","GPS":"5103'10.11"Nord 1349'20.48"Ost","Hoehe":"190"}]
Alles klar, das hier ist das Problem.
Du hast hier mehrfach verschachtelte Anführungszeichen, wo darüber hinaus noch beide Arten von möglichen Anführungszeichen vorkommen. Das jetzt so zu konstruieren, dass das eval das gewünschte Ergebnis bringt ist schwierig.
Der String müsste so aussehen:
var request = {};
request.responseText = '[{"WebCamName":"Rockau","Protokoll":"ws444","GPS":"5101\'42.05\\"Nord 1351\'42.83\\"Ost","Hoehe":"252"},{"WebCamName":"Loschwitz","Protokoll":"ws2300","GPS":"5103\'10.11\\"Nord 1349\'20.48\\"Ost","Hoehe":"190"}]';
var x = (eval(request.responseText));
alert(x[0].GPS)
Struppi.
Hallo Struppi!
Alles klar, das hier ist das Problem.
Genau genommen hab ich ja gar kein Problem mehr. Zumindest läuft das Script jetzt Fehlerfrei und liefert mir dabei sogar noch das gewünschte Ergebnis ;)
Alles weitere sind (für mich) jetzt nur noch Details.
Du hast hier mehrfach verschachtelte Anführungszeichen, wo darüber hinaus noch beide Arten von möglichen Anführungszeichen vorkommen. Das jetzt so zu konstruieren, dass das eval das gewünschte Ergebnis bringt ist schwierig.
Wie bereits weiter oben geschrieben, bin ich davon ausgegangen, dass die Pear-Klasse das für mich alles notwendige erledigt.
Der String müsste so aussehen:
request.responseText = '[{"WebCamName":"Rockau","Protokoll":"ws444","GPS":"5101\'42.05\\"Nord 1351\'42.83\\"Ost","Hoehe":"252"},{"WebCamName":"Loschwitz","Protokoll":"ws2300","GPS":"5103\'10.11\\"Nord 1349\'20.48\\"Ost","Hoehe":"190"}]';
Fast. Wieso z.B. 42.05\"Nord? Es bleibt an der Stelle doch bei 1 . Als Ausgabe möchte ich doch 42.05"Nord. Dasselbe mit 20.48\"Ost.
Aber wieso verursacht das Script keine Fehler mit den "nicht escapten" einfachen Anführungszeichen? Oder ist das der Grund warum es mit eval('('+..+')') läuft? eval() _ohne_ einfache Anführungszeichen habe ich, zugegeben, nicht einmal getestet.
Danke und Grüße, Matze
Alles klar, das hier ist das Problem.
Genau genommen hab ich ja gar kein Problem mehr. Zumindest läuft das Script jetzt Fehlerfrei und liefert mir dabei sogar noch das gewünschte Ergebnis ;)
OK, dann hast du uns aber vermutlich nicht den Code gezeigt, der wirklich in der Ausgabe übermittelt wird.
Der String müsste so aussehen:
request.responseText = '[{"WebCamName":"Rockau","Protokoll":"ws444","GPS":"5101\'42.05\\"Nord 1351\'42.83\\"Ost","Hoehe":"252"},{"WebCamName":"Loschwitz","Protokoll":"ws2300","GPS":"5103\'10.11\\"Nord 1349\'20.48\\"Ost","Hoehe":"190"}]';
Fast. Wieso z.B. 42.05\"Nord? Es bleibt an der Stelle doch bei 1 . Als Ausgabe möchte ich doch 42.05"Nord.
Genau das passiert. Der Punkt ist du hast einen "text mit "Anführungszeichen"" wenn du da jetzt eval drüberlaufen läßt, sieht das JS die Anführungszeichen in den Anführungszeichen, daher muss die Maskierung maskiert werden, damit sie im eval Block zum tragen kommt.
Aber wieso verursacht das Script keine Fehler mit den "nicht escapten" einfachen Anführungszeichen?
Vermutlich sind die Anführungszeichen maskiert und wie hast du den response text ermittelt?
Struppi.
Hallo Struppi!
OK, dann hast du uns aber vermutlich nicht den Code gezeigt, der wirklich in der Ausgabe übermittelt wird.
Eigentlich hab ich gar nichts gezeigt was ausgegeben wird.
Mit document.getElementById('cam').innerHTML = stats[0].GPS;
erhalte ich 5101'42.05"Nord 1351'42.83"Ost - genau das, was ich will.
Aber wieso verursacht das Script keine Fehler mit den "nicht escapten" einfachen Anführungszeichen?
Vermutlich sind die Anführungszeichen maskiert und wie hast du den response text ermittelt?
So
require_once("JSON/JSON.php"); // die PEAR-Klasse
$myjson = new Services_JSON();
print(trim($myjson->encode($array)));
$array enthält die 2 Datensätze der MySQL-Abfrage. Ein ganz normales PHP-Array.
Grüße, Matze
Moin!
var foo = eval('request.responseText');
document.getElementById('test').innerHTML = stats.length;
>
> wobei request.responseText das JSON-Array ist.
> Ich dachte die Ausagbe mit .length gibt mir die Anzahl der Elemente des Arrays, es gibt mir aber die Länge des Arrays als String wieder.
>
> Was mache ich da falsch? Ich weiß nicht wie ich das erste und das zweite "Element0" z.B. ausgeben kann. Bzw. halt dessen Wert.
Schade, dass von den zwei bisherigen Antwortern niemand das Offensichtliche gesehen hat - obwohl vor allem Struppi drüber stolpern hätte müssen, da sein Gegenbeispiel den Fehler ja gerade eben NICHT macht:
Das Argument von eval() muss der auszuführende Code sein. Der in deinem Beispiel auszuführende Code lautet "request.responseText". Wenn dieser Code ausgeführt wird, wird er den Inhalt dieser Objekteigenschaft zurückgeben, die landen in der Variablen foo, und der Rest ergibt sich dann.
Der Inhalt der Objekteigenschaft ist dein JSON-String. Den willst du nicht wieder per eval() herausfinden, dazu hättest du einfacher schreiben können: `var foo = request.responseText;`{:.language-javascript}
Was du eigentlich willst, ist das Evaluieren des JSON, also des Strings, der in request.responseText enthalten ist: `var foo = eval(request.responseText);`{:.language-javascript}. Man beachte die Abwesenheit von Anführungszeichen.
Und jetzt noch ein SICHERHEITSHINWEIS: Es ist grundsätzlich keine so gute Idee, skriptgesteuert wirklich nacktes JSON auszugeben und in Javascript unbehandelt in eval() zu tun, was aber weniger daran liegt, dass eval() damit böse Sachen macht, sondern daran, dass das JSON-generierende Skript nicht nur auf AJAX-Requests antwortet, sondern grundsätzlich auf ALLE Requests, die von Browsern kommen. Relevant wird dies, wenn in dem JSON geheimzuhaltende Informationen stehen, die man nur abrufen kann, wenn man sich gegenüber dem Server authentifiziert hat!
Folgendes Szenario, um das Problem zu verdeutlichen: Ein regulärer Benutzer loggt sich ein und ruft eine Seite mit AJAX-Funktion auf. Danach ruft er aber auch eine Seite auf, die ohne sein Wissen böse Absichten hat. Die böse Seite kann zwar nicht per AJAX auf den Loginbereich zugreifen, aber es funktioniert mittels <script src="http://login.example.org/ajax/jsonskript"></script> - und wenn vorher das Standardverhalten beim Erzeugen neuer Objekte ein wenig abgeändert wurde, wird der JSON-Code, den das Skript ausgibt, so abgefangen, dass Javascript die Daten ebenfalls als Variable nutzen kann!
Das verhindert man am einfachsten, indem man den JSON-String in einen Javascript-Kommentar setzt, und diese Kommentarzeichen per String-Operation vor dem eval() wieder entfernt.
- Sven Rautenberg
--
"Love your nation - respect the others."
Schade, dass von den zwei bisherigen Antwortern niemand das Offensichtliche gesehen hat - obwohl vor allem Struppi drüber stolpern hätte müssen, da sein Gegenbeispiel den Fehler ja gerade eben NICHT macht:
Logisch :-( - ich hatte gestern einen im Tee :-)
Ich kann mich aber erinner dass es mir aufgefallen ist und hatte mich gewundert, aber dann mich so auf eval konzentriert, dass ich den Punkt verdrängt hatte.
Da ich bisher weder mit JSON noch mit eval besonders viel gemacht habe, wollte ich sehen was das Eigentlich genau macht. Interessant ist z.b. das:
var y=eval('{x:"50"}'); // 50
var y=eval('({x:"50"})'); // [Object Object]
var y=eval('{"x":"50"}'); // invalid Label
var y=eval('({"x":"50"})'); // [Object Object]
Das erste verstehe ich eigentlich nicht.
var y = {x: 50};
ergibt ein Objekt, aber var y = eval '{x: 50}';
ergibt 50. Das ist wohl das was Timo bereits gesagt hatte und x ist hier nur ein Label.
Naja, und dann übersieht man manchmal beim "basteln" die offensichtlichen Dinge.
Struppi.
Das erste verstehe ich eigentlich nicht.
var y = {x: 50};
ergibt ein Objekt, abervar y = eval '{x: 50}';
ergibt 50. Das ist wohl das was Timo bereits gesagt hatte und x ist hier nur ein Label.
Wieso verstehst du das nich? Ist doch logisch: Im Kontext von var blub = ...; wird eine Expression erwartet, daher ist {...} an der Stelle nie ein Block, sondern immer ein Object Literal. Aber eval() führt auch Statements aus und gibt das Ergebnis des letzten Expression Statements zurück. Wenn ich einfach
{
bla :
5
}
in mein Script schreibe ohne Kontext, dann ist es natürlich ein Block. Das sieht auch eval so. Wenn der Kontext aber (...) ist, also eine Expression, dann sieht eval es ebenfalls als Object Literal an.
Mathias
{
bla :
5
}in mein Script schreibe ohne Kontext, dann ist es natürlich ein Block. Das sieht auch eval so. Wenn der Kontext aber (...) ist, also eine Expression, dann sieht eval es ebenfalls als Object Literal an.
Mal etwas ganz anderes: Welchen Sinn haben eigentlich diese Blöcke*? Einen eigenen Scope haben sie ja nicht.
* außerhalb solcher Sachen wie function
, if
, for
, etc.
Welchen Sinn haben eigentlich diese Blöcke*?
Meines Wissens keinen. Da habe ich auch noch nicht durchgeblickt.
Mathias
Meines Wissens keinen. Da habe ich auch noch nicht durchgeblickt.
Gut, dann packe ich das auf den Haufen "Dinge, die JavaScript kann, die ich aber nicht benutze", wo schon with
und Labels liegen.
Hallo,
Mal etwas ganz anderes: Welchen Sinn haben eigentlich diese Blöcke*? Einen eigenen Scope haben sie ja nicht.
* außerhalb solcher Sachen wiefunction
,if
,for
, etc.
Die sind wirklich sinnvoll, wenn sie bei anderen Statements benutzt werden. Das kommt aus der syntaktischen Definition, die da so lautet:
if ( Expression ) Statement else Statement
Statement kann nun alles mögliche sein, eben auch ein Block. Die Dinger dienen also wirklich nur dazu, die Block-Syntax in if, while, try, for und so zur Verfügung zu stellen, also sozusagen für den Entwickler des Parsers das ganze überschaubarer zu machen. Da es aber definiert ist, kann man es auch an jeglicher Stelle im Quellcode hinsetzen, wo ein Statement erlaubt ist. Die Dinger sind also aus der syntaktischen Definition nach oben geschwappt. Das isses aber auch schon.
Tim
Es ist grundsätzlich keine so gute Idee, skriptgesteuert wirklich nacktes JSON auszugeben
Jein.
wenn vorher das Standardverhalten beim Erzeugen neuer Objekte ein wenig abgeändert wurde
Das funktioniert allerdings nur in einigen Browsern, und die haben es mittlerweile aus Sicherheitsgründen deaktiviert.
Das verhindert man am einfachsten, indem man den JSON-String in einen Javascript-Kommentar setzt, und diese Kommentarzeichen per String-Operation vor dem eval() wieder entfernt.
Der Kommentar müsste das JSON ja »kaputt« machen, sodass es kein ausführbares JavaScript mehr ist. Also kein (korrekter) JavaScript-Kommentar, sondern <blablub>...</blablub>, crashme();, throw "nönö!"; oder so etwas.
Eigentlich reicht es aus, wenn man direkt { ... } schreibt, ohne Klammern. Und nicht [ ... ] schreibt, auch wenn das gemäß JSON erlaubt wäre. Dann ist der Code nur mit eval() zu verarbeiten, beim Einbinden als Script löst er den besagten Fehler aus. Die Klammern werden dann beim eval() hinzugefügt bzw. sind im Falle der Nutzung einer nativen oder eigenen (d.h. Crockfords) JSON-Implementierung unnötig.
Am besten verhindert man solche Angriffe mit serverseitigem CSRF-Schutz, der auch viele andere Fälle abdeckt.
Mathias
Hallo Mathias!
Das verhindert man am einfachsten, indem man den JSON-String in einen Javascript-Kommentar setzt, und diese Kommentarzeichen per String-Operation vor dem eval() wieder entfernt.
Eigentlich reicht es aus, wenn man direkt { ... } schreibt, ohne Klammern. Und nicht [ ... ] schreibt, auch wenn das gemäß JSON erlaubt wäre. Dann ist der Code nur mit eval() zu verarbeiten, beim Einbinden als Script löst er den besagten Fehler aus. Die Klammern werden dann beim eval() hinzugefügt bzw. sind im Falle der Nutzung einer nativen oder eigenen (d.h. Crockfords) JSON-Implementierung unnötig.
Also das JSON habe ich mit der Pear-Klasse von Michal Migurski erstellt. Das heißt, daher kommen auch die eckigen Klammern.
Ich steh grad ein bisschen auf dem Schlauch und weiß nicht ob ich die Klammern jetzt per Hand entfernen und ins JavaScript eval('('[+request.responseText+]')') schreiben soll um sie wieder hinzuzufügen. Von Crockford hör ich grad zum ersten mal. Gibts wieder was zu googlen...^^
Danke und Grüße, Matze
Also das JSON habe ich mit der Pear-Klasse von Michal Migurski erstellt. Das heißt, daher kommen auch die eckigen Klammern.
Die eckigen Klammern sind vollkommen richtig, du hast ja ein Array. Aber wenn der Code aus einer fertigen Klasse kommt, dann ist diese fehlerhaft, da sie - wie ich ich schon erwähnte - falsch mit den Anführungszeichen umgeht.
Struppi.
Hallo Struppi!
Die eckigen Klammern sind vollkommen richtig, du hast ja ein Array. Aber wenn der Code aus einer fertigen Klasse kommt, dann ist diese fehlerhaft, da sie - wie ich ich schon erwähnte - falsch mit den Anführungszeichen umgeht.
Ich will zwar nicht dauernd im Thread hoch und runter springen aber nunja.
Tja, was soll ich da tun? Wenn selbst die auf JSON.org verlinkte Klasse fehlerhaft ist, womit sollte ich das Array dann erstellen?
Danke und Grüße, Matze
Tja, was soll ich da tun? Wenn selbst die auf JSON.org verlinkte Klasse fehlerhaft ist, womit sollte ich das Array dann erstellen?
Nein, sie ist nicht fehlerhaft, sonst hättest du ja nicht die richtige Ausgabe. Allerdings kann ich dein Problem nicht nachvollziehen, was passiert denn wenn du, wie schon vorgeschlagen, var x = eval(request.responseText);
schreibst?
Das sollte eigentlich bei deinen Daten funktionieren.
Struppi.
Hallo Struppi!
Nein, sie ist nicht fehlerhaft, sonst hättest du ja nicht die richtige Ausgabe. Allerdings kann ich dein Problem nicht nachvollziehen, was passiert denn wenn du, wie schon vorgeschlagen,
var x = eval(request.responseText);
schreibst?
Das sollte eigentlich bei deinen Daten funktionieren.
Ja, tut es auch. Ich habe aber gerade noch ein anderes Problem entdeckt :(
Grüße, Matze
Also das JSON habe ich mit der Pear-Klasse von Michal Migurski erstellt.
Ist bei dir json_encode verfügbar (ab PHP 5.2)?
Mathias
Hallo!
Also das JSON habe ich mit der Pear-Klasse von Michal Migurski erstellt.
Ist bei dir json_encode verfügbar (ab PHP 5.2)?
Ja, aber ich hab grad getestet und 2 Sachen festgestellt.
Zum einen heißt es nicht "GPS":"5101'42.05"Nord 1351'42.83"Ost" sondern "GPS":"51°01'42.05"Nord 13°51'42.83"Ost". Man achte auf die Punkte ° (Grad)
Nun, mit json_encode() ergibt "GPS":"51°01'42.05"Nord 13°51'42.83"Ost" nur noch "GPS":"51". Mit der PEAR-Klasse verschwinden die Kreise °.
Entschuldigt bitte, das ist mir gerade erst aufgefallen :(
Langsam könnte ich verzweifeln, ich dachte schon "ich habs"...
Grüße, Matze
Moin!
wenn vorher das Standardverhalten beim Erzeugen neuer Objekte ein wenig abgeändert wurde
Das funktioniert allerdings nur in einigen Browsern, und die haben es mittlerweile aus Sicherheitsgründen deaktiviert.
Das sollte trotzdem kein Grund sein, es nicht dennoch aktiv zu verhindern. :)
Das verhindert man am einfachsten, indem man den JSON-String in einen Javascript-Kommentar setzt, und diese Kommentarzeichen per String-Operation vor dem eval() wieder entfernt.
Der Kommentar müsste das JSON ja »kaputt« machen, sodass es kein ausführbares JavaScript mehr ist. Also kein (korrekter) JavaScript-Kommentar, sondern <blablub>...</blablub>, crashme();, throw "nönö!"; oder so etwas.
Eben:
/* [JSON-String] */
Den Code kann man nicht per <script> ausführen lassen.
Am besten verhindert man solche Angriffe mit serverseitigem CSRF-Schutz, der auch viele andere Fälle abdeckt.
Tja, und wie macht man das? :)
- Sven Rautenberg
Am besten verhindert man solche Angriffe mit serverseitigem CSRF-Schutz, der auch viele andere Fälle abdeckt.
Tja, und wie macht man das? :)
Üblicherweise indem man alle URIs, die serverseitige Änderungen vornehmen, durch Tokens schützt. Der steht einmal in dem Formular, von dem der Benutzer die Änderung vornimmt, und wird beim Abrufen des Formulars in der Session auf dem Server gespeichert (wahlweise im Cookie gespeichert). Wenn der Token aus den Formulardaten und der Session nicht übereinstimmen, liegt eine CSRF vor.
JSON-Ausgaben nehmen serverseitig natürlich nicht unbedingt Änderungen vor, daher könnte man sie bei o.g. Schutz immer noch via <script> abgreifen. Aber das wird wie gesagt bereits durch { ... }, Auskommentierung usw. verhindert.
Mathias
Hallo Sven!
Das Argument von eval() muss der auszuführende Code sein. Der in deinem Beispiel auszuführende Code lautet "request.responseText". Wenn dieser Code ausgeführt wird, wird er den Inhalt dieser Objekteigenschaft zurückgeben, die landen in der Variablen foo, und der Rest ergibt sich dann.
Achso, das leuchtet ein. Danke für die Erklärung.
Was du eigentlich willst, ist das Evaluieren des JSON, also des Strings, der in request.responseText enthalten ist:
var foo = eval(request.responseText);
. Man beachte die Abwesenheit von Anführungszeichen.
Das leuchtet mir auch ein. eval('('+...+')') will mir aber noch nicht so recht in den Kopf.
Danke und Grüße, Matze