688 Stimmen

Zugriff auf verschachtelte JavaScript-Objekte und -Arrays über einen String-Pfad

Ich habe eine Datenstruktur wie diese:

var someObject = {
    'part1' : {
        'name': 'Part 1',
        'size': '20',
        'qty' : '50'
    },
    'part2' : {
        'name': 'Part 2',
        'size': '15',
        'qty' : '60'
    },
    'part3' : [
        {
            'name': 'Part 3A',
            'size': '10',
            'qty' : '20'
        }, {
            'name': 'Part 3B',
            'size': '5',
            'qty' : '20'
        }, {
            'name': 'Part 3C',
            'size': '7.5',
            'qty' : '20'
        }
    ]
};

Und ich möchte mit diesen Variablen auf die Daten zugreifen:

var part1name = "part1.name";
var part2quantity = "part2.qty";
var part3name1 = "part3[0].name";

part1name sollte gefüllt werden mit someObject.part1.name Wert, der "Teil 1" ist. Dasselbe gilt für part2quantity, das mit 60 gefüllt ist.

Gibt es irgendwie zu erreichen dies entweder mit reinen Javascript oder JQuery?

0 Stimmen

Sie sind sich nicht sicher, was Sie hier fragen? Möchten Sie part1.name abfragen können und den Text "part1.name" zurückerhalten? Oder möchten Sie den in part1.name gespeicherten Wert abrufen?

0 Stimmen

Haben Sie versucht, etwas zu tun wie var part1name = someObject.part1name; `

1 Stimmen

@BonyT : Ich möchte someObject.part1.name abfragen und den Wert davon zurückgeben ("Part 1"). Ich möchte jedoch, dass die Abfrage (ich nannte sie "den Schlüssel") in einer Variablen 'part1name' gespeichert wird. Vielen Dank für Ihre Antwort. @3nigma : Das habe ich sicherlich. Aber das ist nicht meine Absicht. Vielen Dank für die Antwort.

1voto

abernier Punkte 25010

Ich hatte vor kurzem die gleiche Frage und habe erfolgreich https://npmjs.org/package/tea-properties die auch set verschachtelte Objekte/Arrays :

bekommen:

var o = {
  prop: {
    arr: [
      {foo: 'bar'}
    ]
  }
};

var properties = require('tea-properties');
var value = properties.get(o, 'prop.arr[0].foo');

assert(value, 'bar'); // true

gesetzt:

var o = {};

var properties = require('tea-properties');
properties.set(o, 'prop.arr[0].foo', 'bar');

assert(o.prop.arr[0].foo, 'bar'); // true

0 Stimmen

"Dieses Modul wurde abgekündigt. Verwenden Sie chaijs/pathval."

1voto

Eineki Punkte 14433

Wenn Sie auf verschiedene verschachtelte Schlüssel zugreifen müssen, ohne sie zum Zeitpunkt der Codierung zu kennen (es wird trivial sein, sie anzusprechen), können Sie den Array-Notation-Accessor verwenden:

var part1name = someObject['part1']['name'];
var part2quantity = someObject['part2']['qty'];
var part3name1 =  someObject['part3'][0]['name'];

Sie entsprechen dem Accessor der Punktnotation und können z.B. zur Laufzeit variieren:

var part = 'part1';
var property = 'name';

var part1name = someObject[part][property];

ist gleichbedeutend mit

var part1name = someObject['part1']['name'];

oder

var part1name = someObject.part1.name;

Ich hoffe, das beantwortet Ihre Frage...

EDIT

Ich werde keine Zeichenfolge verwenden, um eine Art von xpath zu erhalten Abfrage um auf einen Objektwert zuzugreifen. Da Sie eine Funktion aufrufen müssen, um die Abfrage zu parsen und den Wert abzurufen, würde ich einen anderen Weg einschlagen (nicht :

var part1name = function(){ return this.part1.name; }
var part2quantity = function() { return this['part2']['qty']; }
var part3name1 =  function() { return this.part3[0]['name'];}

// usage: part1name.apply(someObject);

oder, wenn Sie sich nicht mit dem anwenden. Methode

var part1name = function(obj){ return obj.part1.name; }
var part2quantity = function(obj) { return obj['part2']['qty']; }
var part3name1 =  function(obj) { return obj.part3[0]['name'];}

// usage: part1name(someObject);

Die Funktionen sind kürzer und übersichtlicher, der Interpreter prüft sie für Sie auf Syntaxfehler und so weiter.

Übrigens bin ich der Meinung, dass eine einfache Zuweisung zum richtigen Zeitpunkt ausreicht...

0 Stimmen

Interessant. Aber in meinem Fall ist das someObject noch nicht initialisiert, wenn ich part1name einen Wert zuweise. Ich kenne nur die Struktur. Deshalb verwende ich String, um die Struktur zu beschreiben. Und ich hoffe, dass ich damit meine Daten von someObject abfragen kann. Vielen Dank für den Austausch Ihrer Gedanken :)

0 Stimmen

@Komaruloh : Ich denke, Sie würden schreiben, dass das Objekt noch NICHT initialisiert ist, wenn Sie Ihre Variablen erstellen. Im Übrigen verstehe ich nicht, warum Sie die Zuweisung nicht zum richtigen Zeitpunkt vornehmen können?

0 Stimmen

Entschuldigung, dass ich nicht erwähnt habe, dass someObject noch nicht initialisiert ist. Was den Grund betrifft, so wird someObject über einen Webdienst abgerufen. Und ich möchte ein Array von Header haben, die aus part1name, part2qty, etc. bestehen. So, dass ich nur Schleife durch die Kopfzeile Array und erhalten den Wert, den ich wollte, basierend auf part1name Wert als "Schlüssel"/Pfad zu someObject.

0voto

jumpjack Punkte 680

Ausgehend von der Antwort von @Alnitak habe ich diesen Quellcode erstellt, der eine aktuelle JSON-Datei herunterlädt und verarbeitet, wobei für jeden Schritt erklärende Zeichenfolgen auf der Konsole ausgegeben werden, sowie weitere Details, falls ein falscher Schlüssel übergeben wird:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <script>
function retrieveURL(url) {
        var client = new XMLHttpRequest();
        prefix = "https://cors-anywhere.herokuapp.com/"
        client.open('GET', prefix + url);
        client.responseType = 'text';
        client.onload = function() {
            response = client.response; // Load remote response.
            console.log("Response received.");
            parsedJSON  = JSON.parse(response);
            console.log(parsedJSON);
            console.log(JSONitemByPath(parsedJSON,"geometry[6].obs[3].latituade"));
            return response;
        };
        try {
            client.send();
        } catch(e) {
            console.log("NETWORK ERROR!");
            console.log(e);
        }
}

function JSONitemByPath(o, s) {
    structure = "";
    originalString = s;
    console.log("Received string: ", s);
    s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
    console.log("Converted to   : ", s);
    s = s.replace(/^\./, '');           // strip a leading dot
    var a = s.split('.');

    console.log("Single keys to parse: ",a);

    for (var i = 0, n = a.length; i < n; ++i) {
        var k = a[i];
        if (k in o) {
            o = o[k];
            console.log("object." + structure +  a[i], o);
            structure +=  a[i] + ".";
        } else {
            console.log("ERROR: wrong path passed: ", originalString);
            console.log("       Last working level: ", structure.substr(0,structure.length-1));
            console.log("       Contents: ", o);
            console.log("       Available/passed key: ");
            Object.keys(o).forEach((prop)=> console.log("       "+prop +"/" + k));
            return;
        }
    }
    return o;
}

function main() {
    rawJSON = retrieveURL("http://haya2now.jp/data/data.json");
}

</script>
  </head>
  <body onload="main()">
  </body>
</html>

Beispiel für die Ausgabe:

Response received.
json-querier.html:17 {geometry: Array(7), error: Array(0), status: {…}}
json-querier.html:34 Received string:  geometry[6].obs[3].latituade
json-querier.html:36 Converted to   :  geometry.6.obs.3.latituade
json-querier.html:40 Single keys to parse:  (5) ["geometry", "6", "obs", "3", "latituade"]
json-querier.html:46 object.geometry (7) [{…}, {…}, {…}, {…}, {…}, {…}, {…}]
json-querier.html:46 object.geometry.6 {hayabusa2: {…}, earth: {…}, obs: Array(6), TT: 2458816.04973593, ryugu: {…}, …}
json-querier.html:46 object.geometry.6.obs (6) [{…}, {…}, {…}, {…}, {…}, {…}]
json-querier.html:46 object.geometry.6.obs.3 {longitude: 148.98, hayabusa2: {…}, sun: {…}, name: "DSS-43", latitude: -35.4, …}
json-querier.html:49 ERROR: wrong path passed:  geometry[6].obs[3].latituade
json-querier.html:50        Last working level:  geometry.6.obs.3
json-querier.html:51        Contents:  {longitude: 148.98, hayabusa2: {…}, sun: {…}, name: "DSS-43", latitude: -35.4, …}
json-querier.html:52        Available/passed key: 
json-querier.html:53        longitude/latituade
json-querier.html:53        hayabusa2/latituade
json-querier.html:53        sun/latituade
json-querier.html:53        name/latituade
json-querier.html:53        latitude/latituade
json-querier.html:53        altitude/latituade
json-querier.html:18 undefined

0voto

ThatGuyRob Punkte 126

React-Beispiel - Verwendung von lodash

Dies ist vielleicht nicht der effizienteste Weg, was die Leistung angeht, aber wenn Ihre Anwendung ein Monolith ist, wird es Ihnen sicherlich einige Zeit sparen. Vor allem, wenn Sie Ihr Statusdatenformat eng an ein API-Backend koppeln.

   import set from "lodash/set";  // More efficient import

    class UserProfile extends Component {

      constructor(props){
        super(props);

        this.state = {
          user: {
            account: {
              id: "",
              email: "",
              first_name: ""
            }
          }
        }
      }

       /**
       * Updates the state based on the form input
       * 
       * @param {FormUpdate} event 
       */
      userAccountFormHook(event) {
        // https://lodash.com/docs#get
        // https://lodash.com/docs#set
        const { name, value } = event.target;
        let current_state = this.state
        set(current_state, name, value)  // Magic happens here
        this.setState(current_state);
      }

    render() {
        return (
          <CustomFormInput
            label: "First Name"
            type: "text"
            placeholder: "First Name"
            name: "user.account.first_name"
            onChange: {this.userAccountFormHook}
            value: {this.state.user.account.first_name}

          />
      )
  }
}

0voto

Aakash Punkte 17068

Arbeiten mit Underscore 's property o propertyOf :

var test = {
  foo: {
    bar: {
      baz: 'hello'
    }
  }
}
var string = 'foo.bar.baz';

// document.write(_.propertyOf(test)(string.split('.')))

document.write(_.property(string.split('.'))(test));

<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>

Viel Glück...

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X