Werte mehrerer Schlüssel aus verschachtelten Objekten in JSON abrufen (ohne jQuery)

130797
user1613163

Ich würde gerne fragen, ob meine JSON-Daten schlecht durchdacht sind und ob die Lösung, die ich gelöst habe, besonders ineffizient / einfach dumm / typisch ist.

Angesichts der folgenden JSON-Daten:

{
    "User01": {
        "dates & times": {
            "date 01": "150",
            "date 02": "165",
            "date 03": "180"
        }
    },

    "User02": {
        "dates & times": {
            "date 01": "150",
            "date 02": "165",
            "date 03": "180"
        }
    },

    "User03": {
        "dates & times": {
            "date 01": "150",
            "date 02": "165",
            "date 03": "180"
        }
    }
}

... und die Datums- und Zeitangaben abrufen möchten, damit sie gerendert werden können, z.

Date 01: Time 01
Date 02: Time 02
Date 03: Time 03

... und was ich damit erreicht habe:

for (var key in myObj){
    if (key == selUser){
        for (var date in myObj[key]["dates & times"]){
            console.log("Date: " + date + "; " + "weight: " + myObj[key]["dates & times"][date]);
            var dtTag = "<dt class=\"date\"><span>Date: </span>" + date + " </dt>";
            var ddTag = "<dd class=\"value\"><span>Time: </span>" + myObj[key]["dates & times"][date] + "</dd>";
            output.innerHTML += dtTag;
            output.innerHTML += ddTag;
        }
    } // if 
} // loop

Zu den Json-Daten: Angenommen, es könnte Hunderte von Datums- und Zeiteinträgen geben, ist dies sogar eine rechtmäßige Verwendung von Json, oder sollten diese Daten mit Arrays besser formatiert werden, z.

{ "dates & times":
    {
        "dates": [ "date01", "date02", "date03" ],
        "times": [ "150", "165", "180" ]
    }
}

Und in einem solchen Fall, in dem ich keine Kontrolle über die JSON-Daten hatte, wie könnte ich meine Lösung verbessern, um den ausgewählten Benutzer zu durchlaufen und die Daten des verschachtelten Objekts erneut zu durchlaufen?

Übrigens, dies ist im Zusammenhang mit dem Studium von JavaScript, nicht jQuery oder einer anderen Bibliothek / Framework.

Antworten
9
Sind die Namen buchstäblich "Datum 01" usw.? Wenn ja, warum nicht einfach "" Datums- und Zeitangaben "" zu einem Array von Zeitwerten machen und die Zeichenfolge aus dem Index erstellen? cbojar vor 6 Jahren 0
Sie sollten auf jeden Fall ein Array anstelle von "User01", "User02", ... verwenden. Schism vor 6 Jahren 0
@cbojar Nein, die Namen sind nicht wörtlich "Datum 01" usw .; Dies sind tatsächliche Daten, z. B. 2014.08.25, dh Sätze von Datums- / Zeitdatenpaaren für jeden Benutzer user1613163 vor 6 Jahren 0
@Schism Thx für die sugg. Ziemlich sicher, irgendwann in dev hatte ich eine Reihe von Benutzern, aber das ist eine neue Frage, wie man die Daten wie beschrieben abruft. Möchten Sie einen Hinweis geben? Vielen Dank! user1613163 vor 6 Jahren 0
@Schism Btw, was ich damit meinte, war, dass ich davon ausgegangen bin, dass die Benutzer ein Array sein sollten. wäre es so etwas wie 'for (var key in myObj.Users) {...'? user1613163 vor 6 Jahren 0
Willkommen bei Code Review. Wenn Sie das nächste Mal eine Frage stellen, würden wir es sehr vorziehen, dass Sie realistische Bezeichner (möglicherweise "swimSessions" anstelle von "myObj") und realistische Daten (z. B. "2014.08.25" anstelle von "150") verwenden. Es ist schwer, Fragen zu beantworten, wenn wir nicht sagen können, was Sie buchstäblich meinen und was hypothetisch ist. 200_success vor 6 Jahren 0
@ 200_erfolg Thx dafür - hab es bekommen. user1613163 vor 6 Jahren 0

1 Antwort auf die Frage

8
cbojar
{ "dates & times":
    {
        "dates": [ "date01", "date02", "date03" ],
        "times": [ "150", "165", "180" ]
    }
}

Nein, mach das nicht. Sie nehmen eine explizite Beziehung in einer Datenstruktur an und machen diese implizit zwischen zwei Datenstrukturen. Stattdessen:

{ "dates & times": [
    { "date": "2014-08-24", "time": "150" },
    { "date": "2014-08-24", "time": "165" },
    { "date": "2014-08-24", "time": "180" },
] }

Jetzt ist die Beziehung explizit und Sie können das Array einfacher und sicherer durchlaufen als das Durchlaufen der Tasten. (Sicher, denn wenn eine Eigenschaft hinzugefügt wird Object.prototype, wird sie als Schlüssel angezeigt.)

for (var key in myObj){
    if (key == selUser){
        for (var date in myObj[key]["dates & times"]){
            console.log("Date: " + date + "; " + "weight: " + myObj[key]["dates & times"][date]);
            var dtTag = "<dt class=\"date\"><span>Date: </span>" + date + " </dt>";
            var ddTag = "<dd class=\"value\"><span>Time: </span>" + myObj[key]["dates & times"][date] + "</dd>";
            output.innerHTML += dtTag;
            output.innerHTML += ddTag;
        }
    } // if 
} // loop

Das ist etwas mehr als absolut notwendig. Die äußere Schleife ist überflüssig, da wir eigentlich nur für einen Schlüssel etwas tun . Die innere Schleife ändert sich mit unserer neuen Datenstruktur. Außerdem können wir uns ein wenig umstrukturieren, um die Leistung etwas zu verbessern. Wir werden auch die ifAnweisung in eine Guard-Klausel umwandeln, um den Codepfad zu verdeutlichen.

// Is this key in the object, and does it have the right property?
if(!myObj[selUser] || !myObj[selUser]["dates & times"]) { // return, throw error, whatever }

output.innerHTML += myObj[selUser]["dates & times"].map(function(el){
    console.log("Date: " + el.date + "; Time: " + el.time);
    var dtTag = "<dt class=\"date\"><span>Date: </span>" + el.date + "</dt>";
    var ddTag = "<dd class=\"value\"><span>Time: </span>" + el.time + "</dd>";

    return dtTag + ddTag;
}).join("");

Dies basiert auf einer neueren ES5-Funktion. Wenn Sie ältere Browser unterstützen müssen, können Sie sie mit entsprechenden Loops ausfüllen oder ersetzen (siehe unten). Außerdem gibt dieser Code die von Ihnen angegebene Ausgabe, FYI, nicht genau aus.


Ohne Array # map:

// Is this key in the object, and does it have the right property?
if(!myObj[selUser] || !myObj[selUser]["dates & times"]) { // return, throw error, whatever }

var i, el, dtTag, ddTag;

var listItems = [];
var datesAndTimes = myObj[selUser]["dates & times"];
var datesAndTimesLength = datesAndTimes.length;

for(i = 0; i < datesAndTimesLength; i++) {
    el = datesAndTimes[i];
    console.log("Date: " + el.date + "; Time: " + el.time);
    dtTag = "<dt class=\"date\"><span>Date: </span>" + el.date + "</dt>";
    ddTag = "<dd class=\"value\"><span>Time: </span>" + el.time + "</dd>";

    listItems.push(dtTag + ddTag);
}

output.innerHTML += listItems.join("");
Das ist viel für mich zu verarbeiten, aber ich werde es sorgfältig lesen und ausprobieren. Nochmals vielen Dank - sehr geschätzt! user1613163 vor 6 Jahren 0
@ user1613163 Es ist möglicherweise einfacher, die Version ohne Array # map zuerst mit der eigenen zu vergleichen, da sie die Komplexität nicht abrundet. cbojar vor 6 Jahren 0
re: "Die äußere Schleife ist überflüssig, da wir eigentlich nur etwas für einen Schlüssel tun" ... die äußere Schleife ist, wie ich einen angegebenen Benutzer anvisiere (ergo var selUser) ... gibt es eine bessere Methode? user1613163 vor 6 Jahren 0
Ändert diese Tatsache tatsächlich irgendeinen anderen Code, den Sie vorschlagen? (Ich lerne es immer noch), aber wie gesagt, es gibt eine Benutzerauswahl und der Json enthält die Daten für mehrere Benutzer, also habe ich die äußere Schleife verwendet, um anzugeben. Prost! user1613163 vor 6 Jahren 0
@ user1613163 In JS können Objekte wie Ihr JSON als assoziative Arrays verwendet werden, sodass die Schlüssel nicht durchsucht werden müssen. Wir können nur den Namen der Eigenschaft indizieren. Wenn also "selUser" "User02" ist, werden mit myObj [selUser] die Daten für Benutzer 02 abgerufen. cbojar vor 6 Jahren 0
Danke nochmal. Ich habe meine .json-Daten entsprechend angepasst: {"Benutzer": [{"Benutzername": "Herbie". Jetzt habe ich jedoch Probleme, den ausgewählten Benutzer als Ziel festzulegen. Ist das immer noch etwas, das ich ohne Schleife machen kann, um diesen Benutzer zu finden? user1613163 vor 6 Jahren 0
@ user1613163 Nein, in diesem Fall müssen Sie das Array nach dem korrekten Benutzernamen durchsuchen. Wenn der Datensatz groß ist und Sie viele verschiedene Benutzer suchen müssen, Sie ihn jedoch weiterhin als Array behalten möchten, können Sie ihn sortieren und eine binäre Suche verwenden, um die Suchzeit zu optimieren. cbojar vor 6 Jahren 0
Danke für die Klarstellung. Hätte ich mit dem Org-Sugg gelaufen, dass eine Schleife nicht notwendig war, hätte ich mich verrückt gemacht, als ich meinen SelUser ohne Schleife gefunden hätte;) Sehr verpflichtet! user1613163 vor 6 Jahren 0