it-swarm.com.de

JSON finden in JavaScript

Gibt es einen besseren Weg, als Daten in JSON zu finden? Es ist zum Bearbeiten und Löschen.

for(var k in objJsonResp) {
  if (objJsonResp[k].txtId == id) {
    if (action == 'delete') {
      objJsonResp.splice(k,1);
    } else {
      objJsonResp[k] = newVal;
    }
    break;
  }
}

Die Daten sind als Liste von Karten angeordnet.

[
  {id:value, pId:value, cId:value,...},
  {id:value, pId:value, cId:value,...},
  ...
]
54
zapping

(Sie suchen nicht in "JSON", sondern in einem Array. Die JSON-Zeichenfolge wurde bereits in ein Objektdiagramm deserialisiert, in diesem Fall in ein Array.)

Einige Optionen:

Verwenden Sie ein Objekt anstelle eines Arrays

Wenn Sie die Erzeugung dieses Dings kontrollieren, muss es ein Array sein ? Wenn nicht, gibt es einen viel einfacheren Weg.

Angenommen, dies sind Ihre ursprünglichen Daten:

[
    {"id": "one",   "pId": "foo1", "cId": "bar1"},
    {"id": "two",   "pId": "foo2", "cId": "bar2"},
    {"id": "three", "pId": "foo3", "cId": "bar3"}
]

Könnten Sie stattdessen Folgendes tun?

{
    "one":   {"pId": "foo1", "cId": "bar1"},
    "two":   {"pId": "foo2", "cId": "bar2"},
    "three": {"pId": "foo3", "cId": "bar3"}
}

Dann ist es ganz einfach, den entsprechenden Eintrag anhand der ID zu finden:

id = "one"; // Or whatever
var entry = objJsonResp[id];

... wie es aktualisiert wird:

objJsonResp[id] = /* New value */;

... und entferne es:

delete objJsonResp[id];

Dies nutzt die Tatsache aus, dass Sie in JavaScript ein Objekt mit einem Eigenschaftsnamen als Zeichenfolge indizieren können - und diese Zeichenfolge kann ein Literal sein oder aus einer Variablen stammen, wie oben in id.

Eingabe einer ID-zu-Index-Karte

(Dumme Idee, geht dem oben Gesagten voraus. Wird aus historischen Gründen aufbewahrt.)

Es sieht so aus, als müsste dies ein Array sein. In diesem Fall gibt es keinen besseren Weg, als das Array zu durchsuchen, es sei denn, Sie möchten eine Karte darauf platzieren, was Sie tun könnten, wenn Sie die Kontrolle über die Generierung des Arrays hätten Objekt. Sagen Sie zum Beispiel, Sie haben dies ursprünglich:

[
    {"id": "one",   "pId": "foo1", "cId": "bar1"},
    {"id": "two",   "pId": "foo2", "cId": "bar2"},
    {"id": "three", "pId": "foo3", "cId": "bar3"}
]

Der generierende Code könnte eine ID-zu-Index-Zuordnung bereitstellen:

{
    "index": {
        "one": 0, "two": 1, "three": 2
    },
    "data": [
        {"id": "one",   "pId": "foo1", "cId": "bar1"},
        {"id": "two",   "pId": "foo2", "cId": "bar2"},
        {"id": "three", "pId": "foo3", "cId": "bar3"}
    ]
}

Dann ist es trivial, einen Eintrag für die ID in der Variablen id zu bekommen:

var index = objJsonResp.index[id];
var obj = objJsonResp.data[index];

Dies nutzt die Tatsache aus, dass Sie Objekte mithilfe von Eigenschaftsnamen indizieren können.

Wenn Sie dies tun, müssen Sie natürlich die Karte aktualisieren, wenn Sie das Array ändern, was zu einem Wartungsproblem werden kann.

Wenn Sie jedoch nicht die Kontrolle über die Generierung des Objekts haben oder wenn das Aktualisieren der Zuordnung von IDs zu Indizes zu viel Code und/oder Wartungsprobleme verursacht, müssen Sie eine Brute-Force-Suche durchführen.

Brute Force Search (korrigiert)

Etwas OT (obwohl Sie gefragt haben , ob es einen besseren Weg gibt :-)), aber Ihren Code zum Durchlaufen eines Arrays ist falsch. Details hier , aber Sie können for..in nicht verwenden, um Array-Indizes zu durchlaufen (oder wenn Sie dies tun, müssen Sie besondere Anstrengungen unternehmen, um dies zu tun); for..in durchläuft die Eigenschaften eines Objekts , nicht die Indizes eines Arrays . Ihre beste Wette mit einem nicht-spärlichen Array (und Ihre ist nicht-spärlich) ist eine herkömmliche Standardschleife:

var k;
for (k = 0; k < someArray.length; ++k) { /* ... */ }

oder

var k;
for (k = someArray.length - 1; k >= 0; --k) { /* ... */ }

Was auch immer Sie bevorzugen (letzteres ist nicht immer in allen Implementierungen schneller, was für mich nicht intuitiv ist, aber wir sind da). (Bei einem spärlichen Array können Sie for..in verwenden, aber auch hier besondere Anstrengungen unternehmen, um Fallstricke zu vermeiden. Weitere Informationen finden Sie im oben verlinkten Artikel.)

Die Verwendung von for..in für ein Array scheint in einfachen Fällen zu funktionieren , da Arrays Eigenschaften für jeden ihrer Indizes und ihre einzigen anderen Standardeigenschaften haben ( length und ihre Methoden) sind als nicht aufzählbar gekennzeichnet. Es bricht jedoch ab, sobald Sie andere Eigenschaften für das Array-Objekt festlegen (oder ein Framework legt diese fest) (was durchaus gültig ist; Arrays sind nur Objekte mit einer besonderen Behandlung der Eigenschaft length).

183
T.J. Crowder

Ich war auf dieses Problem bei einem komplexen Modell mit mehreren verschachtelten Objekten gestoßen. Ein gutes Beispiel für das, was ich mir angesehen habe, wäre folgendes: Nehmen wir an, Sie haben ein Polaroid von sich. Und dieses Bild wird dann in einen Kofferraum eines Autos gesteckt. Das Auto befindet sich in einer großen Kiste. Die Kiste befindet sich im Laderaum eines großen Schiffes mit vielen anderen Kisten. Ich musste den Laderaum durchsuchen, in die Kisten schauen, den Kofferraum überprüfen und dann nach einem vorhandenen Bild von mir suchen.

Ich konnte im Internet keine guten Lösungen finden, und .filter() funktioniert nur auf Arrays. Die meisten Lösungen schlagen vor, einfach zu prüfen, ob model["yourpicture"] vorhanden ist. Dies war sehr unerwünscht, da aus diesem Beispiel nur der Laderaum des Schiffes durchsucht werden würde und ich einen Weg brauchte, um sie weiter aus dem Kaninchenbau zu bekommen.

Dies ist die rekursive Lösung, die ich gemacht habe. In Kommentaren bestätigte ich von T.J. Crowder, dass eine rekursive Version erforderlich wäre. Ich dachte, ich würde es teilen, falls jemand auf eine ähnliche komplexe Situation stoßen würde.

function ContainsKeyValue( obj, key, value ){
    if( obj[key] === value ) return true;
    for( all in obj )
    {
        if( obj[all] != null && obj[all][key] === value ){
            return true;
        }
        if( typeof obj[all] == "object" && obj[all]!= null ){
            var found = ContainsKeyValue( obj[all], key, value );
            if( found == true ) return true;
        }
    }
    return false;
}

Dies beginnt bei einem bestimmten Objekt im Diagramm und führt alle gefundenen Objekte erneut aus. Ich benutze es so:

var liveData = [];
for( var items in viewmodel.Crates )
{
    if( ContainsKeyValue( viewmodel.Crates[items], "PictureId", 6 ) === true )
    {
        liveData.Push( viewmodel.Crates[items] );
    }
}

Dadurch wird ein Array der Kisten erzeugt, die mein Bild enthielten.

8
Travis J

Zapping - Sie können diese Javascript-Lib verwenden; DefiantJS. Es ist nicht erforderlich, JSON-Daten in Objekte umzustrukturieren, um die Suche zu erleichtern. Stattdessen können Sie die JSON-Struktur mit einem XPath-Ausdruck wie folgt durchsuchen:

    var data = [
   {
      "id": "one",
      "pId": "foo1",
      "cId": "bar1"
   },
   {
      "id": "two",
      "pId": "foo2",
      "cId": "bar2"
   },
   {
      "id": "three",
      "pId": "foo3",
      "cId": "bar3"
   }
],
res = JSON.search( data, '//*[id="one"]' );

console.log( res[0].cId );
// 'bar1'

DefiantJS erweitert das globale Objekt JSON um eine neue Methode. "Suche", die das Array mit den Übereinstimmungen zurückgibt (leeres Array, wenn keines gefunden wurde) Sie können es selbst ausprobieren, indem Sie Ihre JSON-Daten einfügen und verschiedene XPath-Abfragen hier testen:

http://www.defiantjs.com/#xpath_evaluator

XPath ist, wie Sie wissen, eine standardisierte Abfragesprache.

6
Hakan Bilgin

Wenn Sie dies an mehreren Stellen in Ihrer Anwendung durchführen, ist es sinnvoll, eine clientseitige JSON-Datenbank zu verwenden, da das Erstellen benutzerdefinierter Suchfunktionen unübersichtlich und weniger wartbar ist als die Alternative.

Schauen Sie sich ForerunnerDB an, das ein sehr leistungsfähiges clientseitiges JSON-Datenbanksystem bietet und eine sehr einfache Abfragesprache enthält, die Ihnen hilft, genau das zu tun, was Sie suchen:

// Create a new instance of ForerunnerDB and then ask for a database
var fdb = new ForerunnerDB(),
    db = fdb.db('myTestDatabase'),
    coll;

// Create our new collection (like a MySQL table) and change the default
// primary key from "_id" to "id"
coll = db.collection('myCollection', {primaryKey: 'id'});

// Insert our records into the collection
coll.insert([
    {"name":"my Name","id":12,"type":"car owner"},
    {"name":"my Name2","id":13,"type":"car owner2"},
    {"name":"my Name4","id":14,"type":"car owner3"},
    {"name":"my Name4","id":15,"type":"car owner5"}
]);

// Search the collection for the string "my nam" as a case insensitive
// regular expression - this search will match all records because every
// name field has the text "my Nam" in it
var searchResultArray = coll.find({
    name: /my nam/i
});

console.log(searchResultArray);

/* Outputs
[
    {"name":"my Name","id":12,"type":"car owner"},
    {"name":"my Name2","id":13,"type":"car owner2"},
    {"name":"my Name4","id":14,"type":"car owner3"},
    {"name":"my Name4","id":15,"type":"car owner5"}
]
*/

Haftungsausschluss: Ich bin der Entwickler von ForerunnerDB.

0
Rob Evans

Wenn die JSON-Daten in Ihrem Array auf irgendeine Weise sortiert sind, können Sie verschiedene Suchvorgänge ausführen. Wenn Sie jedoch nicht mit vielen Daten zu tun haben, werden Sie wahrscheinlich mit einer O(n) -Operation hier (wie Sie es tun) in Ordnung sein. Alles andere wäre wahrscheinlich übertrieben.

0
Justin Swartsel