Huber: Von XML zu JSON (Hilfe)

Da unser Lehrer uns nun aufgetragen hat unser Projekt dahingehend zu verändern das wir JSON mit einbinden sollen, stehen wir vor einem Problem. Da wir uns mit der Materie bisher nicht auskennenm hoffe ich hier im Forum auf Hilfe zu stoßen. Unser Projekt ist soweit fertig, müssen nur noch kleinere Änderungnen vornehmen und halt von XML zu JSON übergehen. Ich stelle hier nun die meiner Meinung nach die wichtigen Dateien hoch die geändert werden müssten.

Zuerst das funktionierde Projekt mit XML:
Datei 1 "Fotoantwort.jsp"
<%
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("pragma","no-cache");
%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><?xml version="1.0" ?>
<Bildaustausch><!-- in dieser .jsp Datei wird eine XMl zur Auswertung durch das aufrufende JavaScript generiert. -->
    <c:forEach var="item" items="${fotoBean.array}"><!-- Fuer jedes vorhandene Bild wird ein neues Bildelement erstellt -->
        <Bild>
            <url>${item[0]}</url><!-- Hier werden die Daten aus der FotoDataBean in das XML Dokument eingebunden -->
            <name>${item[1]}</name>
            <text>${item[2]}</text>
            <datum>${item[3]}</datum>
            <laenge>${item[4]}</laenge>
        </Bild>
    </c:forEach>
</Bildaustausch>

---------------------------------------------------------

Datei 2 "Controller.java"
package servlet;
import java.io.IOException;
//import java.io.PrintWriter;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// Dieses Servlet nimmt alles clientseitigen Anfragen entgegen, leitet sie zur Bearbeitung an die entsprecheden Beans weiter und gibt das Resultat der Bearbeitung an die dafür vorgesehene .jsp weiter.
public class Controller extends HttpServlet {
private FotoBean foto;
private GalerienBean galerien;

public void init(){  
	foto = new FotoBean();  
	galerien = new GalerienBean();  
}  
  
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{  
	String jsp;  
	// An dieser Stelle wird entschieden um welche Art der Anfrage es sich handelt  
	if(request.getParameter("Mappe") != null){ //Es handelt sich um eine Anfrage nach Bildern  
		FotoDataBean fotoBean = new FotoDataBean(foto.getBilder(request));//Die entsprechenden Daten werden durch eine FotoBean ermittlet, in einer FotoDataBean gespeichert und schließlich zur Darstellung der FotoAntwort.jsp zugewiesen  
		request.setAttribute("fotoBean", fotoBean);  
		jsp ="../html/FotoAntwort.jsp";  
	}else{  
		jsp ="../html/Fotogalerie5.jsp"; // Hier handelt es sich um eine Anfrage nach dem auf dem Server vorhanden Fotomappen. Das weitere Vorgehen ist das Gleiche wie bereits oben beschrieben.  
		GalerienDataBean galerienBean = new GalerienDataBean(galerien.getGalerien());  
		request.setAttribute("galerienBean",galerienBean);  
	}  
	RequestDispatcher dipatcher = request.getRequestDispatcher(jsp); // An dieser Stelle wird die Anfrage zur Darstellung an die entsprechende .jsp weitergeleitet.  
	dipatcher.forward(request, response);  
	System.out.println(request.getParameter("Mappe"));  
}  

}

---------------------------------------------------

Datei 3 "anfragen.js"
//Dies ist die JavaScript Datei, die asynchrone Anfragen an den Server stellt und die durch das Servlet generierten antworten entgegen nimmt
var client;
var mappe;
var Sortierung = "a";
var AngezeigteBreite = 500;
var GespeicherteBreite = 0;
var time=2000;
var timeout;
var stop=false;
var a;

function galerieAnfrage(a,b,c,d){
    showProgress(); //An dieser Stelle wird die Wartenzeige eingeblendet
    var Laenge = 0;
    var Anfang = 0;

if(a != null){//Hier werden die bei Aufruf der Funktion übermittelten Parameter ausgewertet
     mappe = a;
    }
    if(d != null){
     Sortierung = d;
    }
    if(b == "minus"){
            Anfang = -1;
    }
    if(b == "plus"){
         Anfang = 1;
    }
    if(c == "minus"){
        Laenge = -1;
    }
    if(c == "plus"){
        Laenge = 1;
    }
    if(mappe == null){//Wenn noch keine Fotomappe ausgewählt wurde soll auch noch kein Request an den Server möglich sein.
      alert("Bitte waehlen Sie zunaechst eine Fotomappe aus.");
    }else{
        //Hier wird ein neuer Request an das Servelett generiert und als Parameter die gewünschte Modifikationen an der Sortierung, der Anzahl der anzuzeigenden Vorschaubilder und der Scrollposition übermittelt. Außerdem wird der Eventhandler der für das Behandlen der Serverantwort zuständig ist definiert
        client = new XMLHttpRequest();
        client.onreadystatechange = eventHandler02;
        client.open("GET","../servlet/Controller?Mappe=" + mappe + "&Anfang=" + Anfang + "&Laenge=" + Laenge + "&Sortierung=" + Sortierung);
        client.send(null);
    }
}

function eventHandler01(){//Dies ist der EventHandler der für die Bearbeitung der Serverantwort auf die oben stehende Anfrage verantwortlich ist
if(client.readyState == 4){
if(client.status == 200){
    document.getElementById("minus").style.visibility = "visible"; // Hier werden die Scrollschaltflächen und die Bildererhöhungs- und Bildererniedrigungsschaltflächen sichtbar gemacht
    document.getElementById("plus").style.visibility = "visible";
    document.getElementById("links").style.visibility = "visible";
    document.getElementById("rechts").style.visibility = "visible";
    document.getElementById("slide").style.visibility = "visible";
    document.getElementById("text").style.visibility = "visible";
    document.getElementById("sek").style.visibility = "visible";
    document.getElementById("stopp").style.visibility = "visible";
    document.getElementById("fort").style.visibility = "visible";
    document.getElementById("Upload").style.visibility = "visible";
    var url = client.responseXML.getElementsByTagName("url"); //Hier werden die einzelnen durch die FotoAntwort.jsp in Form eines XML Dokuments generierten Antworten ausgelesen
    var name = client.responseXML.getElementsByTagName("name");
    var text = client.responseXML.getElementsByTagName("text");
    var datum = client.responseXML.getElementsByTagName("datum");
    var laenge = client.responseXML.getElementsByTagName("laenge");
    var bilder = "";

	    for(i = 0; i < url.length; ++i){//An dieser Stelle werden die im aktuellen Dokument anzuzeigenden Vorschubilder aufgelistet. Hierbei wird auch schon gleich das mouseoverevent, das später für die Großdarstellung eines Bildes verantwortlich ist, mit allen hierfür erforderlichen Parametern vorbereitet.  
	    	 		  bilder = bilder + "<img src='" + url[i].firstChild.nodeValue+"' width='90' height='60' alt='test' onclick='javascript:klick(\""+url[i].firstChild.nodeValue+"\")' onmouseover='javascript:grossbild(\""+url[i].firstChild.nodeValue+"\",\""+name[i].firstChild.nodeValue+"\",\""+text[i].firstChild.nodeValue+"\",\""+datum[i].firstChild.nodeValue+"\",\""+laenge[i].firstChild.nodeValue+"\")'>";  
	    }  
	    document.getElementById("pictures").innerHTML = bilder; // Hier wird die eben erstellte Bilderliste in das aktuelle Dokument eingehängt  
	  
	} else{  
		alert(client.status);  
	}  
	hideProgress(); // Hier wird die Fortschrittsanzeige ausgeblendet  
}  

}

----------------------------------------------------------------------

Mit XML funktioniert es alles einwandfrei nun haben wir die FotoAntwort.jsp wie folgt umgeändert.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <%@ taglib prefix="js" uri="http://www.atg.com/taglibs/json" %>

<!--<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">-->

js:object
<c:forEach var="item" items="${fotoBean.array}">
<js:property name="url" value="${item[0]}"></js:property>
<js:property name="name" value="${item[1]}"></js:property>
<js:property name="text" value="${item[2]}"></js:property>
<js:property name="datum" value="${item[3]}"></js:property>
<js:property name="laenge" value="${item[4]}"></js:property>
</c:forEach>
</js:object>

--------------

Wie schaffen wir es nun den JSON String anzusprechen, auszugeben und weiterzuverarbeiten wie wir es vorher mit XML gemacht haben?
Haben schon einige Beispiele durchgeguckt sind aber nie auf den richtigen Lösungsweg gestoßen. Falls jemand helfen könnte wären wir sehr froh. Wenn noch weitere Details des Programmcodes von Nöten sind liefer ich den auch gerne nach.

Gruß Huber

  1. Hallo,

    bei einem XMLHttpRequest hast du den JSON-Code in der Eigenschaft responseText (statt responseXML). Du musst diesen String noch selbst in ein JavaScript-Objekt parsen, um in JavaScript auf die Daten zugreifen zu können. Das kannst du mit JSON.parse() machen. Das window.JSON-Objekt sowie die parse-Methode haben einige Browser schon nativ eingebaut, für den Rest gibt es einen JSON-Parser in JavaScript, den du einbinden kannst: http://www.json.org/js.html.

    Prüfe mal die Ausgabe deines FotoAntwort.jsp. Da sollte nur JSON-Code drinstehen. Der MIME-Typ sollte application/json sein. Kein HTML-Code, auch keine Kommentare.
    Anstelle eines Objects solltest du einen Array verwenden. Den kannst du nach dem Parsen einfach durchlaufen.

    Beispiel
    JSON-String der JSP:
    [ { "url" : "bild.jpg", "name" : "Hallo Welt", ... }, ... ]

    JavaScript-Verarbeitung:

    var bilderHTML = '';  
    var bilder = JSON.parse(client.responseText);  
    for (var i = 0, l = bilder.length; i < l; i++) {  
      var bild = bilder[i];  
      bilderHTML += '<img src="' + bild.url + '">' + bild.name; // usw.  
    }
    

    Das ist im Grunde viel einfacher als XML-DOM.

    Mathias

    1. Hallo,

      bei einem XMLHttpRequest hast du den JSON-Code in der Eigenschaft responseText (statt responseXML). Du musst diesen String noch selbst in ein JavaScript-Objekt parsen, um in JavaScript auf die Daten zugreifen zu können. Das kannst du mit JSON.parse() machen. Das window.JSON-Objekt sowie die parse-Methode haben einige Browser schon nativ eingebaut, für den Rest gibt es einen JSON-Parser in JavaScript, den du einbinden kannst: http://www.json.org/js.html.

      Prüfe mal die Ausgabe deines FotoAntwort.jsp. Da sollte nur JSON-Code drinstehen. Der MIME-Typ sollte application/json sein. Kein HTML-Code, auch keine Kommentare.
      Anstelle eines Objects solltest du einen Array verwenden. Den kannst du nach dem Parsen einfach durchlaufen.

      Beispiel
      JSON-String der JSP:
      [ { "url" : "bild.jpg", "name" : "Hallo Welt", ... }, ... ]

      JavaScript-Verarbeitung:

      var bilderHTML = '';

      var bilder = JSON.parse(client.responseText);
      for (var i = 0, l = bilder.length; i < l; i++) {
        var bild = bilder[i];
        bilderHTML += '<img src="' + bild.url + '">' + bild.name; // usw.
      }

      
      >   
      > Das ist im Grunde viel einfacher als XML-DOM.  
      >   
      > Mathias  
        
      Hallo und danke für die schnelle Antwort. Habe den MIME-Typ in der FotoAntwortJSON umgestellt das war schonmal ein sehr guter Tipp. Danke. Jetzt habe ich nur den Code zur Verarbeitung in den EventHandler eingesetzt und es einmal durchlaufen lassen. Jetzt gibt mir Firebug im Firefox einen Fehler aus bei der Zeile" var bilder = JSON.parse(client.responseText);"  
      Muss ich den Inhalt aus der FotoAntwortJSON noch nach Ihrem Beispiel anpassen oder reicht es so wie es ist?  
        
      Gruß Huber
      
      1. Hi,

        Jetzt gibt mir Firebug im Firefox einen Fehler aus bei der Zeile" var bilder = JSON.parse(client.responseText);"

        Bitte benenne Fehlermeldungen im Wortlaut - nur mit „gibt einen Fehler aus“ können wir wenig anfangen.

        MfG ChrisB

        --
        RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
        1. Hi,

          Jetzt gibt mir Firebug im Firefox einen Fehler aus bei der Zeile" var bilder = JSON.parse(client.responseText);"

          Bitte benenne Fehlermeldungen im Wortlaut - nur mit „gibt einen Fehler aus“ können wir wenig anfangen.

          MfG ChrisB

          Hallo hier ist die genaue Fehlermeldung aus Firebug:
          "rotes(X)" JSON.parse
          [Break on this error] var bilder = JSON.parse(client.responseText);

          Gruß Huber

          1. Hi,

            Jetzt gibt mir Firebug im Firefox einen Fehler aus bei der Zeile" var bilder = JSON.parse(client.responseText);"

            Bitte benenne Fehlermeldungen im Wortlaut - nur mit „gibt einen Fehler aus“ können wir wenig anfangen.

            MfG ChrisB

            Hallo hier ist die genaue Fehlermeldung aus Firebug:
            "rotes(X)" JSON.parse
            [Break on this error] var bilder = JSON.parse(client.responseText);

            Gruß Huber

            So habe das den EventHandler nun wie folgt verändert:
            function eventHandler02(){
            if(client.readyState == 4){
            if(client.status == 200){
            alert(client.responseText);
                var bilderHTML = '';
                var bilder = JSON.parse(client.responseText);

            	    alert(bilder.length);  
            	    for (i = 0; i < 5; ++i) {  
            	      var bild = bilder[i];  
            	      alert("hallo1");  
            	      bilderHTML = bilderHTML +  '<img src="' + bilder.url + '">' ;  
            	      alert(bilderHTML);  
            	    }  
            	    document.getElementById("pictures").innerHTML = bilderHTML;  
            	  
            	  
            	}else{  
            		alert(client.status);  
            	}  
            	hideProgress(); // Hier wird die Fortschrittsanzeige ausgeblendet  
            }  
            

            }

            So wie der Handler nun ist gibt er mir zumindestens schonmal das letzte Bild so oft aus wie ich es in der for-Schleife angeben (5). Habe es mit bilder.length probiert aber es funktionierte nicht. Habe dann im alert(bilder.length) gesehen das es undefined ist. Und anscheinend gibt mir der JSON.parse(client.responseText); immer nur den letzten Wert zurück. Habe ja eine Fotomappe mit mehreren Bildern und immer das letzte zeigt er mir an. Heißt ja irgendwie das das Array nicht richtig gefüllt wird oder?
            Hoffe jemand hat einen guten Einfall dazu.
            Gruß Huber

            1. So wie der Handler nun ist gibt er mir zumindestens schonmal das letzte Bild so oft aus wie ich es in der for-Schleife angeben (5). Habe es mit bilder.length probiert aber es funktionierte nicht. Habe dann im alert(bilder.length) gesehen das es undefined ist. Und anscheinend gibt mir der JSON.parse(client.responseText); immer nur den letzten Wert zurück. Habe ja eine Fotomappe mit mehreren Bildern und immer das letzte zeigt er mir an. Heißt ja irgendwie das das Array nicht richtig gefüllt wird oder?
              Hoffe jemand hat einen guten Einfall dazu.
              Gruß Huber

              Ok das Thema hat sich erledigt. Der EventHandler ist so schon in Ordnung gewesen. Der Fehler lag in der FotoAntwortJSON.jsp da haben wir immer nur ein Objekt ausgegeben. Wir haben nun ein Array drausgemacht und nun läuft es einwandfrei. Vielen Danke für die Hilfe.
              Gruß Huber

          2. Hallo hier ist die genaue Fehlermeldung aus Firebug:

            Nicht Firebug, sondern die Fehlerkonsole gibt die genau Meldung aus, die sich auch ohne Probleme kopieren läßt. Mit der Meldung läßt sich auch wenig anfangen.

            Struppi.

            1. Hallo hier ist die genaue Fehlermeldung aus Firebug:

              Nicht Firebug, sondern die Fehlerkonsole gibt die genau Meldung aus, die sich auch ohne Probleme kopieren läßt. Mit der Meldung läßt sich auch wenig anfangen.

              Struppi.

              Hallo ansonsten gab es keine andere Fehlermeldung. Habe ja jetzt auch schon einen gewissen Ansatz hingekriegt(anderer Post). Was mir jetzt so daran aufgefallen ist das client.responseText nur den letzten String übergibt. Alle anderen werden vielleicht übersprungen/überschrieben oder sonstwas. Was beim Alert noch aufällt ist das anscheinend zuerst ca. 100 Leerzeichen mitübergeben werden und dann erst der String. Vielleicht hilft das...
              Gruß Huber

              1. Struppi.

                Bitte zitiere nur das, worauf du antwortest, Danke.

                Hallo ansonsten gab es keine andere Fehlermeldung.

                Du weiß, wo du die Fehlerkonsole findest?

                Struppi.