Hoe kan ik geneste objecten, arrays of JSON openen en verwerken?

Ik heb een geneste gegevensstructuur met objecten en arrays. Hoe kan ik de informatie extraheren, d.w.z. toegang krijgen tot een specifieke of meerdere waarden (of sleutels)?

Bijvoorbeeld:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

Hoe krijg ik toegang tot de namevan het tweede item in items?


Antwoord 1, autoriteit 100%

Voorrondes

JavaScript heeft slechts één gegevenstype dat meerdere waarden kan bevatten: Object. Een Arrayis een speciale vorm van object.

(Plain) Objecten hebben de vorm

{key: value, key: value, ...}

Arrays hebben de vorm

[value, value, ...]

Zowel arrays als objecten tonen een key -> valuestructuur. Sleutels in een array moeten numeriek zijn, terwijl elke tekenreeks als sleutel in objecten kan worden gebruikt. De sleutel-waardeparen worden ook wel de “properties”genoemd.

Eigenschappen zijn toegankelijk via puntnotatie

const value = obj.someProperty;

of haakjesnotatie, als de eigenschapsnaam geen geldig JavaScript zou zijn identifier name [spec], of de naam is de waarde van een variabele:

// the space is not a valid character in identifier names
const value = obj["some Property"];
// property name as variable
const name = "some Property";
const value = obj[name];

Daarom zijn array-elementen alleen toegankelijk met haakjes:

const value = arr[5]; // arr.5 would be a syntax error
// property name / index as variable
const x = 5;
const value = arr[x];

Wacht… hoe zit het met JSON?

JSON is een tekstuele weergave van gegevens, net als XML, YAML, CSV en andere. Om met dergelijke gegevens te kunnen werken, moet deze eerst worden geconverteerd naar JavaScript-gegevenstypen, d.w.z. arrays en objecten (en hoe hiermee te werken werd zojuist uitgelegd). Hoe JSON te ontleden wordt uitgelegd in de vraag JSON parseren in JavaScript?.

Verder leesmateriaal

Hoe toegang te krijgen tot arrays en objecten is fundamentele kennis van JavaScript en daarom is het raadzaam om de MDN JavaScript-handleiding, vooral de secties



Toegang tot geneste gegevensstructuren

Een geneste gegevensstructuur is een array of object dat verwijst naar andere arrays of objecten, d.w.z. de waarden zijn arrays of objecten. Dergelijke structuren zijn toegankelijk door achtereenvolgens punt- of haakjesnotatie toe te passen.

Hier is een voorbeeld:

const data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

Laten we aannemen dat we toegang willen tot de namevan het tweede item.

Hier is hoe we het stap voor stap kunnen doen:

Zoals we kunnen zien is dataeen object, vandaar dat we de eigenschappen ervan kunnen benaderen met behulp van puntnotatie. De eigenschap itemsis als volgt toegankelijk:

data.items

De waarde is een array, om toegang te krijgen tot het tweede element, moeten we haakjesnotatie gebruiken:

data.items[1]

Deze waarde is een object en we gebruiken opnieuw puntnotatie om toegang te krijgen tot de eigenschap name. Dus we krijgen uiteindelijk:

const item_name = data.items[1].name;

Als alternatief hadden we haakjesnotatie kunnen gebruiken voor elk van de eigenschappen, vooral als de naam tekens bevatte die het ongeldig zouden hebben gemaakt voor het gebruik van puntnotatie:

const item_name = data['items'][1]['name'];

Ik probeer toegang te krijgen tot een woning, maar ik krijg alleen undefinedterug?

Meestal wanneer u undefinedkrijgt, heeft het object/de array gewoon geen eigenschap met die naam.

const foo = {bar: {baz: 42}};
console.log(foo.baz); // undefined

Gebruik console.logof console.diren inspecteer de structuur van object / array. De eigenschap waartoe u toegang probeert te krijgen, is mogelijk gedefinieerd op een genest object/array.

console.log(foo.bar.baz); // 42

Wat als de eigenschapsnamen dynamisch zijn en ik ze niet van tevoren ken?

Als de eigenschapsnamen onbekend zijn of als we toegang willen tot alle eigenschappen van een object / elementen van een array, kunnen we de for...in[MDN]loop voor objecten en de for[MDN]lus voor arrays om alle eigenschappen / elementen te herhalen.

Objecten

Om alle eigenschappen van datate herhalen, kunnen we het objectals volgt herhalen:

for (const prop in data) {
    // `prop` contains the name of each property, i.e. `'code'` or `'items'`
    // consequently, `data[prop]` refers to the value of each property, i.e.
    // either `42` or the array
}

Afhankelijk van waar het object vandaan komt (en wat u wilt doen), moet u mogelijk in elke iteratie testen of de eigenschap echt een eigenschap van het object is, of dat het een overgeërfde eigenschap is. U kunt dit doen met Object#hasOwnProperty[MDN].

Als alternatief voor for...inmet hasOwnProperty, kunt u Object.keys[MDN]om een array van eigenschapsnamente krijgen:

Object.keys(data).forEach(function(prop) {
  // `prop` is the property name
  // `data[prop]` is the property value
});

Arrays

Om alle elementen van de data.itemsarrayte herhalen, gebruiken we een for-lus:

for(let i = 0, l = data.items.length; i < l; i++) {
    // `i` will take on the values `0`, `1`, `2`,..., i.e. in each iteration
    // we can access the next element in the array with `data.items[i]`, example:
    // 
    // var obj = data.items[i];
    // 
    // Since each element is an object (in our example),
    // we can now access the objects properties with `obj.id` and `obj.name`. 
    // We could also use `data.items[i].id`.
}

Je zou ook for...inkunnen gebruiken om arrays te herhalen, maar er zijn redenen waarom dit moet worden vermeden: Waarom wordt ‘for(var item in list)’ met arrays als slechte praktijk beschouwd in JavaScript?.

Met de toenemende browserondersteuning van ECMAScript 5, de array-methode forEach[MDN]wordt ook een interessant alternatief:

data.items.forEach(function(value, index, array) {
    // The callback is executed for each element in the array.
    // `value` is the element itself (equivalent to `array[index]`)
    // `index` will be the index of the element in the array
    // `array` is a reference to the array itself (i.e. `data.items` in this case)
}); 

In omgevingen die ES2015 (ES6) ondersteunen, kunt u ook de for...of[MDN]lus, die werkt niet alleen voor arrays, maar voor elke iterable :

for (const item of data.items) {
   // `item` is the array element, **not** the index
}

In elke iteratie geeft for...ofons direct het volgende element van de iterabele, er is geen “index” om te openen of te gebruiken.


Wat als de “diepte” van de datastructuur mij niet bekend is?

Naast onbekende sleutels, de “diepte” van de datastructuur (d.w.z. hoeveel geneste objecten) is het ook mogelijk onbekend. Hoe u tot diep geneste eigenschappen kunt openen, is meestal afhankelijk van de exacte gegevensstructuur.

Maar als de gegevensstructuur herhalende patronen bevat, b.v. De weergave van een binaire boom, de oplossing omvat meestal om recursief [WIKIPEDIA] Toegang tot elk niveau van de gegevensstructuur.

Hier is een voorbeeld om het eerste bladknooppunt van een binaire boom te krijgen:

function getLeaf(node) {
    if (node.leftChild) {
        return getLeaf(node.leftChild); // <- recursive call
    }
    else if (node.rightChild) {
        return getLeaf(node.rightChild); // <- recursive call
    }
    else { // node must be a leaf node
        return node;
    }
}
const first_leaf = getLeaf(root);

2, Autoriteit 7%

U hebt deze op deze manier toegang tot

data.items[1].name

of

data["items"][1]["name"]

Beide manieren zijn gelijk.


3, Autoriteit 3%

Objecten en arrays hebben veel ingebouwde methoden die u kunnen helpen met het verwerken van gegevens.

Opmerking: in veel van de voorbeelden gebruik ik pijl functies . Ze zijn vergelijkbaar met functie uitdrukkingen , maar zij Bind de thiswaarde lexicaal.

Object.keys(), Object.values()(ES 2017) en Object.entries()(ES 2017)

Object.keys()Retourneert een reeks van de toetsen van het object, Object.values()retourneert een reeks van de waarden van het object en Object.entries()retourneert een reeks van de toetsen van het object en de bijbehorende waarden in een formaat [key, value].

const obj = {
  a: 1
 ,b: 2
 ,c: 3
}
console.log(Object.keys(obj)) // ['a', 'b', 'c']
console.log(Object.values(obj)) // [1, 2, 3]
console.log(Object.entries(obj)) // [['a', 1], ['b', 2], ['c', 3]]

4, Autoriteit 2%

Soms, toegang tot een genestd object met een string kan wenselijk zijn. De eenvoudige aanpak is het eerste niveau, bijvoorbeeld

var obj = { hello: "world" };
var key = "hello";
alert(obj[key]);//world

Maar dit is vaak niet het geval met complexe JSON. Zoals JSON complexer wordt, worden de benaderingen voor het vinden van waarden binnenin de JSON ook complex. Een recursieve aanpak voor het navigeren van de JSON is het beste en hoe die recursie wordt gebruikt, is afhankelijk van het type gegevens dat wordt gezocht. Als er voorwaardelijke uitspraken zijn, kan een JSON SEARCH een goed hulpmiddel zijn om te gebruiken.

Als de accommodatie die wordt geopend al bekend is, maar het pad is complex, bijvoorbeeld in dit object

var obj = {
 arr: [
    { id: 1, name: "larry" },    
    { id: 2, name: "curly" },
    { id: 3, name: "moe" }
 ]
};

En je weet dat je het eerste resultaat van de array in het object wilt krijgen, misschien zou je dat willen gebruiken

var moe = obj["arr[0].name"];

Dat zal echter een uitzondering veroorzaken omdat er geen eigenschap is van een object met die naam. De oplossing om dit te kunnen gebruiken zou zijn om het boomaspect van het object af te vlakken. Dit kan recursief gedaan worden.

function flatten(obj){
 var root = {};
 (function tree(obj, index){
   var suffix = toString.call(obj) == "[object Array]" ? "]" : "";
   for(var key in obj){
    if(!obj.hasOwnProperty(key))continue;
    root[index+key+suffix] = obj[key];
    if( toString.call(obj[key]) == "[object Array]" )tree(obj[key],index+key+suffix+"[");
    if( toString.call(obj[key]) == "[object Object]" )tree(obj[key],index+key+suffix+".");   
   }
 })(obj,"");
 return root;
}

Nu kan het complexe object worden afgevlakt

var obj = previous definition;
var flat = flatten(obj);
var moe = flat["arr[0].name"];//moe

Hier is een jsFiddle Demovan deze benadering die wordt gebruikt.


Antwoord 5

Om toegang te krijgen tot een genest kenmerk, moet u de naam opgeven en vervolgens het object doorzoeken.

Als u het exacte pad al weet, kunt u het als volgt hardcoderen in uw script:

data['items'][1]['name']

deze werken ook –

data.items[1].name
data['items'][1].name
data.items[1]['name']

Als u de exacte naam niet van tevoren weet, of een gebruiker degene is die de naam voor u opgeeft. Dan is dynamisch zoeken door de datastructuur vereist. Sommigen suggereerden hier dat het zoeken kan worden gedaan met behulp van een for-lus, maar er is een heel eenvoudige manier om een pad te doorkruisen met behulp van Array.reduce.

const data = { code: 42, items: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }] }
const path = [ 'items', '1', 'name']
let result = path.reduce((a,v) => a[v], data)

Het pad is een manier om te zeggen: neem eerst het object met sleutel items, wat toevallig een array is. Neem dan het 1-st element (0 index arrays). Neem als laatste het object met sleutel namein dat array-element, wat toevallig de string baris.

Als je een erg lang pad hebt, kun je zelfs String.splitgebruiken om dit allemaal gemakkelijker te maken –

'items.1.name'.split('.').reduce((a,v) => a[v], data)

Dit is gewoon JavaScript, zonder gebruik te maken van bibliotheken van derden zoals jQuery of lodash.


Antwoord 6

Deze vraag is vrij oud, dus als een eigentijdse update. Met het begin van ES2015 zijn er alternatieven om de gegevens die u nodig heeft te bemachtigen. Er is nu een functie genaamd object destructuringvoor toegang tot geneste objecten.

const data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};
const {
  items: [, {
    name: secondName
  }]
} = data;
console.log(secondName);

Antwoord 7

Je zou de functie lodash _getkunnen gebruiken:

var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.get(object, 'a[0].b.c');
// => 3

Antwoord 8

var ourStorage = {
"desk":    {
    "drawer": "stapler"
  },
"cabinet": {
    "top drawer": { 
      "folder1": "a file",
      "folder2": "secrets"
    },
    "bottom drawer": "soda"
  }
};
ourStorage.cabinet["top drawer"].folder2; // Outputs -> "secrets"

of

//parent.subParent.subsubParent["almost there"]["final property"]

Kortom, gebruik een punt tussen elke afstammeling die zich eronder ontvouwt en als je objectnamen hebt gemaakt van twee strings, moet je de [“obj Name”]-notatie gebruiken. Anders zou een punt voldoende zijn;

Bron: https:// learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-objects

om hieraan toe te voegen, zou toegang tot geneste arrays als volgt gaan:

var ourPets = [
  {
    animalType: "cat",
    names: [
      "Meowzer",
      "Fluffy",
      "Kit-Cat"
    ]
  },
  {
    animalType: "dog",
    names: [
      "Spot",
      "Bowser",
      "Frankie"
    ]
  }
];
ourPets[0].names[1]; // Outputs "Fluffy"
ourPets[1].names[0]; // Outputs "Spot"

Bron: https: / /learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays/

Nog een nuttiger document met de bovenstaande situatie:
https://developer.mozilla.org/en-us / Documenten / Learn / JavaScript / Objects / Basics # Bracket_Notation

Eigendomtoegang via DOT Walking: https: //Developer.mozilla.org/en-us/docs/web/javascript/reference/Operators/property_Accessors#dot_notation


9

Het is eenvoudige uitleg:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};
/*
1. `data` is object contain `item` object*/
console.log(data);
/*
2. `item` object contain array of two objects as elements*/
console.log(data.items);
/*
3. you need 2nd element of array - the `1` from `[0, 1]`*/
console.log(data.items[1]);
/*
4. and you need value of `name` property of 2nd object-element of array)*/
console.log(data.items[1].name);

10

Voor het geval iemand deze vraag in 2017 of later bezoekt en op zoek is naar een gemakkelijk te onthoudenmanier, hier is een uitgebreide blogpost op Toegang tot geneste objecten in JavaScriptzonder te worden misleid

Kan eigenschap ‘foo’ van ongedefinieerdefout niet lezen

1. Oliver Steele’s toegangspatroon voor geneste objecten

De gemakkelijkste en schoonste manier is om Oliver Steele’s geneste objecttoegangspatroon te gebruiken

const name = ((user || {}).personalInfo || {}).name;

Met deze notatie kom je nooit meer tegen

Kan eigenschap ‘naam’ van undefined niet lezen.

U controleert in feite of de gebruiker bestaat, zo niet, dan maakt u ter plekke een leeg object. Op deze manier is de sleutel van het volgende niveau altijd toegankelijk vanuit een bestaand object of een leeg object, maar nooit vanuit een niet-gedefinieerd object.

2. Geneste objecten openen met Array Reduce

Om toegang te krijgen tot geneste arrays, kun je je eigen array schrijven reduce util.

const getNestedObject = (nestedObj, pathArr) => {
    return pathArr.reduce((obj, key) =>
        (obj && obj[key] !== 'undefined') ? obj[key] : undefined, nestedObj);
}
// pass in your object structure as array elements
const name = getNestedObject(user, ['personalInfo', 'name']);
// to access nested array, just pass in array index as an element the path array.
const city = getNestedObject(user, ['personalInfo', 'addresses', 0, 'city']);
// this will return the city from the first address item.

Er is ook een uitstekende typebehandeling minimale bibliotheek typy die dit allemaal voor u doet.


11

Toegang tot Dynamisch Multi-niveaus-object.

var obj = {
  name: "john doe",
  subobj: {
    subsubobj: {
      names: "I am sub sub obj"
    }
  }
};
var level = "subobj.subsubobj.names";
level = level.split(".");
var currentObjState = obj;
for (var i = 0; i < level.length; i++) {
  currentObjState = currentObjState[level[i]];
}
console.log(currentObjState);

Werken Fiddle: https://jsfiddle.net/andreitodorut/3mws3kjl/


12

Hier zijn 4 verschillende methoden vermeld om het object Object te krijgen:

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};
// Method 1
let method1 = data.items[1].name;
console.log(method1);
// Method 2
let method2 = data.items[1]["name"];
console.log(method2);
// Method 3
let method3 = data["items"][1]["name"];
console.log(method3);
// Method 4  Destructuring
let { items: [, { name: second_name }] } = data;
console.log(second_name);

13

Gebruik JSONPath zou een van de meest flexibele oplossingen zijn als u bereid bent om een ​​bibliotheek op te nemen:
https://github.com/s3u/jsonpath (knooppunt en browser)

Voor uw gebruiksgeval zou het JSON-pad zijn:

$..items[1].name

dus:

var secondName = jsonPath.eval(data, "$..items[1].name");

Antwoord 14

Ik geef de voorkeur aan JQuery. Het is overzichtelijker en gemakkelijk te lezen.

$.each($.parseJSON(data), function (key, value) {
  alert(value.<propertyname>);
});

Antwoord 15

Als u op zoek bent naar een of meer objecten die aan bepaalde criteria voldoen, heeft u een paar opties met behulp van query -js

//will return all elements with an id larger than 1
data.items.where(function(e){return e.id > 1;});
//will return the first element with an id larger than 1
data.items.first(function(e){return e.id > 1;});
//will return the first element with an id larger than 1 
//or the second argument if non are found
data.items.first(function(e){return e.id > 1;},{id:-1,name:""});

Er is ook een singleen een singleOrDefault, ze werken ongeveer hetzelfde als respectievelijk firsten firstOrDefault. Het enige verschil is dat ze zullen gooien als er meerdan één match wordt gevonden.

voor verdere uitleg van query-js kun je beginnen met deze post


Antwoord 16

De Underscore js Way

Dit is een JavaScript-bibliotheek die een hele hoop nuttige functional programmingbiedt zonder ingebouwde objecten uit te breiden.

Oplossing:

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};
var item = _.findWhere(data.items, {
  id: 2
});
if (!_.isUndefined(item)) {
  console.log('NAME =>', item.name);
}
//using find - 
var item = _.find(data.items, function(item) {
  return item.id === 2;
});
if (!_.isUndefined(item)) {
  console.log('NAME =>', item.name);
}

Antwoord 17

Oude vraag maar zoals niemand lodash noemde (alleen onderstreping).

Als je lodash al in je project gebruikt, denk ik dat dit een elegante manier is om dit in een complex voorbeeld te doen:

Optie 1

_.get(response, ['output', 'fund', 'data', '0', 'children', '0', 'group', 'myValue'], '')

hetzelfde als:

Optie 2

response.output.fund.data[0].children[0].group.myValue

Het verschil tussen de eerste en tweede optie is dat in de Opt 1als je een van de eigenschappen mist (niet gedefinieerd) in het pad, je geen foutmelding krijgt, het geeft je de derde parameter.

Voor matrixfilter heeft lodash _.find()maar ik gebruik liever het gewone filter(). Maar ik denk nog steeds dat de bovenstaande methode _.get()super handig is bij het werken met echt complexe gegevens. Ik had in het verleden te maken met zeer complexe API’s en dat was handig!

Ik hoop dat het nuttig kan zijn voor wie op zoek is naar opties om echt complexe gegevens te manipuleren, zoals de titel aangeeft.


Antwoord 18

Ik denk niet dat de vraagsteller alleen een genest object op één niveau betreft, dus presenteer ik de volgende demo om te demonstreren hoe toegang te krijgen tot het knooppunt van een diep genest json-object. Oké, laten we het knooppunt met id ‘5’ zoeken.

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'aaa',
    items: [{
        id: 3,
        name: 'ccc'
      }, {
        id: 4,
        name: 'ddd'
      }]
    }, {
    id: 2,
    name: 'bbb',
    items: [{
        id: 5,
        name: 'eee'
      }, {
        id: 6,
        name: 'fff'
      }]
    }]
};
var jsonloop = new JSONLoop(data, 'id', 'items');
jsonloop.findNodeById(data, 5, function(err, node) {
  if (err) {
    document.write(err);
  } else {
    document.write(JSON.stringify(node, null, 2));
  }
});
<script src="https://rawgit.com/dabeng/JSON-Loop/master/JSONLoop.js"></script>

Antwoord 19

In 2020 kunt u @babel/plugin-proposal-optionele-chaining gebruiken. Het is heel eenvoudig om toegang te krijgen tot geneste waarden in een object.

const obj = {
 foo: {
   bar: {
     baz: class {
   },
  },
 },
};
const baz = new obj?.foo?.bar?.baz(); // baz instance
const safe = new obj?.qux?.baz(); // undefined
const safe2 = new obj?.foo.bar.qux?.(); // undefined

https://babeljs.io/docs/en/babel- plugin-proposal-optionele-chaining

https://github.com/tc39/proposal- optional-chaining


Antwoord 20

U kunt de syntaxis jsonObject.keygebruiken om toegang te krijgen tot de waarde. En als u toegang wilt tot een waarde uit een array, dan kunt u de syntaxis jsonObjectArray[index].keygebruiken.

Hier zijn de codevoorbeelden om toegang te krijgen tot verschillende waarden om u een idee te geven.

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};
// if you want 'bar'
console.log(data.items[1].name);
// if you want array of item names
console.log(data.items.map(x => x.name));
// get the id of the item where name = 'bar'
console.log(data.items.filter(x => (x.name == "bar") ? x.id : null)[0].id);

Antwoord 21

Dynamische aanpak

In de onderstaande functie deep(data,key)kunt u een willekeurige key-tekenreeks gebruiken – in uw geval items[1].name(u kunt de array-notatie [i]op elk niveau gebruiken) – als de sleutel ongeldig is, is undefined return.


Antwoord 22

jQuery’s grep-functie laat je door een array filteren:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};
$.grep(data.items, function(item) {
    if (item.id === 2) {
        console.log(item.id); //console id of item
        console.log(item.name); //console name of item
        console.log(item); //console item object
        return item; //returns item object
    }
});
// Object {id: 2, name: "bar"}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

23

// const path = 'info.value[0].item'
// const obj = { info: { value: [ { item: 'it works!' } ], randominfo: 3 }  }
// getValue(path, obj)
export const getValue = ( path , obj) => {
  const newPath = path.replace(/\]/g, "")
  const arrayPath = newPath.split(/[\[\.]+/) || newPath;
  const final = arrayPath.reduce( (obj, k) => obj ?  obj[k] : obj, obj)
  return final;
}

24

Hier is een antwoord met object-scan .

Wanneer u toegang hebt tot één enkele invoer, biedt dit antwoord niet echt veel voordeel op vanille JavaScript. Maar interactie met meerdere velden tegelijkertijd kan dit antwoord meer performant zijn.

Hier is hoe u kunt communiceren met een enkel veld

// const objectScan = require('object-scan');
const data = { code: 42, items: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }] };
const get = (haystack, needle) => objectScan([needle], {
  abort: true,
  rtn: 'value'
})(haystack);
const set = (haystack, needle, value) => objectScan([needle], {
  abort: true,
  rtn: 'bool',
  filterFn: ({ parent, property }) => {
    parent[property] = value;
    return true;
  }
})(haystack);
console.log(get(data, 'items[1].name'));
// => bar
console.log(set(data, 'items[1].name', 'foo2'));
// => true
console.log(data);
// => { code: 42, items: [ { id: 1, name: 'foo' }, { id: 2, name: 'foo2' } ] }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Antwoord 25

Een pythonische, recursieve en functionele benadering om willekeurige JSON-bomen te ontrafelen:

handlers = {
    list:  iterate,
    dict:  delve,
    str:   emit_li,
    float: emit_li,
}
def emit_li(stuff, strong=False):
    emission = '<li><strong>%s</strong></li>' if strong else '<li>%s</li>'
    print(emission % stuff)
def iterate(a_list):
    print('<ul>')
    map(unravel, a_list)
    print('</ul>')
def delve(a_dict):
    print('<ul>')
    for key, value in a_dict.items():
        emit_li(key, strong=True)
        unravel(value)
    print('</ul>')
def unravel(structure):
    h = handlers[type(structure)]
    return h(structure)
unravel(data)

waar dataeen pythonlijst is (geparseerd uit een JSON-tekstreeks):

data = [
    {'data': {'customKey1': 'customValue1',
           'customKey2': {'customSubKey1': {'customSubSubKey1': 'keyvalue'}}},
  'geometry': {'location': {'lat': 37.3860517, 'lng': -122.0838511},
               'viewport': {'northeast': {'lat': 37.4508789,
                                          'lng': -122.0446721},
                            'southwest': {'lat': 37.3567599,
                                          'lng': -122.1178619}}},
  'name': 'Mountain View',
  'scope': 'GOOGLE',
  'types': ['locality', 'political']}
]

Antwoord 26

Als u een pad in een JSON-tekenreeks probeert te vinden, kunt u uw gegevens dumpen in https://jsonpathfinder.com en klik op de GUI-elementen. Het genereert de JS-syntaxis voor het pad naar het element.

Vervang daarnaast, voor alle arrays die u wilt herhalen, de relevante array-offset-indices zoals [0]door een lus.

Hier is een eenvoudigere versie van de tool die u hier kunt uitvoeren. Klik op het knooppunt waarvan u het pad naar uw klembord wilt kopiëren.

/* code minified to make the tool easier to run without having to scroll */                                                         let bracketsOnly=!1,lastHighlighted={style:{}};const keyToStr=t=>!bracketsOnly&&/^[a-zA-Z_$][a-zA-Z$_\d]*$/.test(t)?`.${toHTML(t)}`:`[&quot;${toHTML(t)}&quot;]`,pathToData=t=>`data-path="data${t.join("")}"`,htmlSpecialChars={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;","\t":"\\t","\r":"\\r","\n":"\\n"," ":"&nbsp;"},toHTML=t=>(""+t).replace(/[&<>"'\t\r\n ]/g,t=>htmlSpecialChars[t]),makeArray=(t,e)=>`\n  [<ul ${pathToData(e)}>\n    ${t.map((t,a)=>{e.push(`[${a}]`);const n=`<li ${pathToData(e)}>\n        ${pathify(t,e).trim()},\n      </li>`;return e.pop(),n}).join("")}\n  </ul>]\n`,makeObj=(t,e)=>`\n  {<ul ${pathToData(e)}>\n    ${Object.entries(t).map(([t,a])=>{e.push(keyToStr(t));const n=`<li ${pathToData(e)}>\n        "${toHTML(t)}": ${pathify(a,e).trim()},\n      </li>`;return e.pop(),n}).join("")}\n  </ul>}\n`,pathify=(t,e=[])=>Array.isArray(t)?makeArray(t,e):"object"==typeof t?makeObj(t,e):toHTML("string"==typeof t?`"${t}"`:t),defaultJSON='{\n  "corge": "test JSON... \\n   asdf\\t asdf",\n  "foo-bar": [\n    {"id": 42},\n    [42, {"foo": {"baz": {"ba  r<>!\\t": true, "4quux": "garply"}}}]\n  ]\n}',$=document.querySelector.bind(document),$$=document.querySelectorAll.bind(document),resultEl=$("#result"),pathEl=$("#path"),tryToJSON=t=>{try{resultEl.innerHTML=pathify(JSON.parse(t)),$("#error").innerText=""}catch(t){resultEl.innerHTML="",$("#error").innerText=t}},copyToClipboard=t=>{const e=document.createElement("textarea");e.innerText=t,document.body.appendChild(e),e.select(),document.execCommand("copy"),document.body.removeChild(e)},flashAlert=(t,e=2e3)=>{const a=document.createElement("div");a.textContent=t,a.classList.add("alert"),document.body.appendChild(a),setTimeout(()=>a.remove(),e)},handleClick=t=>{t.stopPropagation(),copyToClipboard(t.target.dataset.path),flashAlert("copied!"),$("#path-out").textContent=t.target.dataset.path},handleMouseOut=t=>{lastHighlighted.style.background="transparent",pathEl.style.display="none"},handleMouseOver=t=>{pathEl.textContent=t.target.dataset.path,pathEl.style.left=`${t.pageX+30}px`,pathEl.style.top=`${t.pageY}px`,pathEl.style.display="block",lastHighlighted.style.background="transparent",(lastHighlighted=t.target.closest("li")).style.background="#0ff"},handleNewJSON=t=>{tryToJSON(t.target.value),[...$$("#result *")].forEach(t=>{t.addEventListener("click",handleClick),t.addEventListener("mouseout",handleMouseOut),t.addEventListener("mouseover",handleMouseOver)})};$("textarea").addEventListener("change",handleNewJSON),$("textarea").addEventListener("keyup",handleNewJSON),$("textarea").value=defaultJSON,$("#brackets").addEventListener("change",t=>{bracketsOnly=!bracketsOnly,handleNewJSON({target:{value:$("textarea").value}})}),handleNewJSON({target:{value:defaultJSON}});
/**/                                                                                       *{box-sizing:border-box;font-family:monospace;margin:0;padding:0}html{height:100%}#path-out{background-color:#0f0;padding:.3em}body{margin:0;height:100%;position:relative;background:#f8f8f8}textarea{width:100%;height:110px;resize:vertical}#opts{background:#e8e8e8;padding:.3em}#opts label{padding:.3em}#path{background:#000;transition:all 50ms;color:#fff;padding:.2em;position:absolute;display:none}#error{margin:.5em;color:red}#result ul{list-style:none}#result li{cursor:pointer;border-left:1em solid transparent}#result li:hover{border-color:#ff0}.alert{background:#f0f;padding:.2em;position:fixed;bottom:10px;right:10px}
<!-- -->                                                                                                    <div class="wrapper"><textarea></textarea><div id="opts"><label>brackets only: <input id="brackets"type="checkbox"></label></div><div id="path-out">click a node to copy path to clipboard</div><div id="path"></div><div id="result"></div><div id="error"></div></div>

Antwoord 27

Lodash gebruiken zou een goede oplossing zijn

Bijvoorbeeld:

var object = { 'a': { 'b': { 'c': 3 } } };                                                                                               
_.get(object, 'a.b.c');                                                                                             
// => 3  

Antwoord 28

Mijn stringdatakomt uit een PHP-bestand, maar toch geef ik het hier aan in var. Wanneer ik mijn json rechtstreeks naar objbreng, zal niets te zien zijn, daarom plaats ik mijn json-bestand als

var obj=JSON.parse(stringdata);
dus daarna krijg ik messageobj en toon in waarschuwingsvak, dan krijg ik datawat json-array is en op te slaan in één variabele ArrObjdan lees ik eerste object van die array met een sleutelwaarde zoals deze ArrObj[0].id

    var stringdata={
        "success": true,
        "message": "working",
        "data": [{
                  "id": 1,
                  "name": "foo"
         }]
      };
                var obj=JSON.parse(stringdata);
                var key = "message";
                alert(obj[key]);
                var keyobj = "data";
                var ArrObj =obj[keyobj];
                alert(ArrObj[0].id);

Other episodes