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.

2voto

Giulio Punkte 311
DotObject = obj => new Proxy(obj, {
  get: function(o,k) {
    const m = k.match(/(.+?)\.(.+)/)
    return m ? this.get(o[m[1]], m[2]) : o[k]
  }
})

const test = DotObject({a: {b: {c: 'wow'}}})
console.log(test['a.b.c'])

1voto

vincent Punkte 1526

Verwendung von Objekt-Scan wird dies zu einem Einzeiler. Noch wichtiger ist jedoch, dass diese Lösung die Leistung berücksichtigt:

  • die Eingabe wird bei der Suche einmal durchlaufen (auch wenn mehrere Schlüssel abgefragt werden)
  • Das Parsing erfolgt nur einmal beim Start (falls mehrere Objekte abgefragt werden)
  • ermöglichen eine erweiterte Syntax mit *

    // const objectScan = require('object-scan');

    const 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' }] };

    const get = (haystack, needle) => objectScan([needle], { rtn: 'value', abort: true })(haystack);

    console.log(get(someObject, 'part1.name')); // => Part 1 console.log(get(someObject, 'part2.qty')); // => 60 console.log(get(someObject, 'part3[0].name')); // => Part 3A

    const getAll = (haystack, ...needles) => objectScan(needles, { reverse: false, rtn: 'entry', joined: true })(haystack);

    console.log(getAll(someObject, 'part1.name', 'part2.qty', 'part3[0].name')); / => [ [ 'part1.name', 'Part 1' ], [ 'part2.qty', '60' ], [ 'part3[0].name', 'Part 3A' ] ] /

    console.log(getAll(someObject, 'part1.')); / => [ [ 'part1.name', 'Part 1' ], [ 'part1.size', '20' ], [ 'part1.qty', '50' ] ] */

    .as-console-wrapper {max-height: 100% !important; top: 0}

    <script src="https://bundle.run/object-scan@13.8.0"></script>

Haftungsausschluss : Ich bin der Autor von Objekt-Scan

1voto

Ben Aston Punkte 48965

Beachten Sie, dass das Folgende nicht für alle gültigen Unicode-Eigenschaftsnamen funktioniert (aber auch für keine der anderen Antworten, soweit ich das beurteilen kann).

const PATTERN = /[\^|\[|\.]([$|\w]+)/gu

function propValue(o, s) {
    const names = []
    for(let [, name] of [...s.matchAll(PATTERN)]) 
        names.push(name)
    return names.reduce((p, propName) => {
        if(!p.hasOwnProperty(propName)) 
            throw 'invalid property name'
        return p[propName]
    }, o)
}

let path = 'myObject.1._property2[0][0].$property3'
let o = {
    1: {
        _property2: [
            [{
                $property3: 'Hello World'
            }]
        ]
    }
}
console.log(propValue(o, path)) // 'Hello World'

1voto

timebandit Punkte 764

Meine Lösung basiert auf der von @AdrianoSpadoni gegebenen und adressiert die Notwendigkeit, das Objekt zu klonen

function generateData(object: any, path: string, value: any): object {
  const clone = JSON.parse(JSON.stringify(object));
  path
    .split(".")
    .reduce(
    (o, p, i) => (o[p] = path.split(".").length === ++i ? value : o[p] || {}),
  clone
);
  return clone;
}

0 Stimmen

Danke @AdrianoSpadoni :+1

1voto

Re9iNee Punkte 356

Ich habe mir alle anderen Antworten angesehen und beschlossen, Verbesserungen in einen besser lesbaren Code einzufügen:

function getObjectValByString(obj, str) {
if (typeof obj === "string") return obj;

const fields = str.split(".");

return getObjectValByString(obj[fields[0]], fields.slice(1).join("."));}

Hier ein Codeschnipsel:

let someObject = {
    partner: {
        id: "AIM",
        person: {
            name: "ANT",
            an: { name: "ESM" },
        },
    },
};

function getObjectValByString(obj, str) {
    if (typeof obj === "string") return obj;

    const fields = str.split(".");

    return getObjectValByString(obj[fields[0]], fields.slice(1).join("."));
}

const result = getObjectValByString(someObject, "partner.person.an.name");
console.log({
    result,
});

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