theadnangondal
theadnangondal

Reputation: 1664

Extract child objects from json object

I am struggling to convert xml to json object and then extracting nodes from the converted object. I am using busyboy to read from the file uploaded on the server. And after that I am using inspect to convert xml to json and then printing the json object. The final output seems as

{ declaration: { attributes: { version: '1.0', encoding: 'utf-8' } },
  root: 
   { name: 'order',
     attributes: 
      { orderid: '123456',
        xmlns: 'http://www.someRandomNameSpace.com' },
     children: 
      [ { name: 'orderperson',
          attributes: {},
          children: [],
          content: 'str1234' },
        { name: 'shipto',
          attributes: {},
          children: 
           [ { name: 'name',
               attributes: {},
               children: [],
               content: 'Adnan Ali' },

I want to read the 'name'='Adnan Ali' from this object how will that be done in nodejs ? I mean how can i reach to the object which has name='name' and content='Adnan Ali'.

The print command is console.log(inspect(order, {colors: true, depth: Infinity}));

Upvotes: 0

Views: 3062

Answers (4)

vincent
vincent

Reputation: 2181

Consider using object-scan. It's very powerful once you wrap your head around it.

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

const find = (input) => objectScan(['**'], {
  abort: true,
  rtn: 'value',
  filterFn: ({ value }) => value.content === 'Adnan Ali' && value.name === 'name'
})(input);

const tobj = { declaration: { attributes: { version: '1.0', encoding: 'utf-8' } }, root: { name: 'order', attributes: { orderid: '123456', xmlns: 'http://www.someRandomNameSpace.com' }, children: [{ name: 'orderperson', attributes: {}, children: [], content: 'str1234' }, { name: 'shipto', attributes: {}, children: [{ name: 'name', attributes: {}, children: [], content: 'Adnan Ali' }] }] } };

console.log(find(tobj));
// => { name: 'name', attributes: {}, children: [], content: 'Adnan Ali' }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Disclaimer: I'm the author of object-scan

Upvotes: 0

x-ray
x-ray

Reputation: 3329

You need to search the arrays of objects for the objects you are interested in. There are various ways to do that, including Array.prototype.find (not sure if it is available in all Node.js versions) and lodash _.find.

Using Array.prototype.filter a solution could look like this (not tested):

function findObject(array, key, value) {
    var filtered = array.filter(obj => (obj[key] === value));
    if (filtered.length !== 1) throw new Error('Found ' + filtered.length + ' objects with `' + key + '`=`' + value + '`, expected to find 1.');
    return filtered[0];
}

var shipto = findObject(input.root.children, 'name', 'shipto');
var name = findObject(shipto.children, 'name', 'name').content;

console.log(name);

Upvotes: 1

keocra
keocra

Reputation: 633

Since you are using NodeJS perhaps giving JSONPath a try would be a good idea. Then you can do something like this:

var jp = require("JSONPath");
var tobj = { "declaration": { "attributes": { "version": '1.0', "encoding": 'utf-8' } },
  "root": 
   { "name": 'order',
     "attributes": 
      { "orderid": '123456',
        "xmlns": 'http://www.someRandomNameSpace.com' },
     "children": 
      [ { "name": 'orderperson',
          "attributes": {},
          "children": [],
          "content": 'str1234' },
        { "name": 'shipto',
          "attributes": {},
          "children": 
           [ { "name": 'name',
               "attributes": {},
               "children": [],
               "content": 'Adnan Ali' 
               }
           ]
        }
    ]
}};
var result = jp.eval(tobj, "$..children[?(@.name === 'name' && @.content === 'Adnan Ali')]");
console.log(result);

Example output:

[ { name: 'name',
    attributes: {},
    children: [],
    content: 'Adnan Ali' } ]

(Don't forget to install JSONPath ;-))

Sources:
https://www.npmjs.com/package/JSONPath
http://goessner.net/articles/JsonPath/

Upvotes: 2

SimpleJ
SimpleJ

Reputation: 14778

You should be able to reach the object with content: 'Adnan Ali' with this path data.root.children[1].children[0]:

const data = {
  declaration: {
    attributes: {
      version: '1.0',
      encoding: 'utf-8'
    }
  },
  root: {
    name: 'order',
    attributes: {
      orderid: '123456',
      xmlns: 'http://www.someRandomNameSpace.com'
    },
    children: [{
      name: 'orderperson',
      attributes: {},
      children: [],
      content: 'str1234'
    }, {
      name: 'shipto',
      attributes: {},
      children: [{
        name: 'name',
        attributes: {},
        children: [],
        content: 'Adnan Ali'
      }]
    }]
  }
};

console.log(data.root.children[1].children[0])

Explanation:

data is an object that contains a root object. root is an object that contains a children array. The second element in root.children (index 1) is an object that contains another children array that contains the object you're looking for at the first index (0).

Upvotes: 1

Related Questions