-3

I iterate over a JSON and I want to find out what is the path of a specific key.

For example I have the JSON:

      `{"address": {
            "city": {
                "type": "string"
            },
            "country": {
                "type": "string"
            },
            "county": {
                "type": "string"
            },
            "street": {
                "car"{
                 "type": "string"
                }
                "type": "string"
            }
         }`

and I want to get the path for key car to refer it in other place.

2 Answers2

1

First you need to correct your JSON because it is invalid. Then you need to parse. Then iterate as follows.

let myObj = `{
  "address": {
    "city": {
      "type": "string"
    },
    "country": {
      "type": "string"
    },
    "county": {
      "type": "string"
    },
    "street": {
      "car": {
        "type": "string"
      },
      "type": "string"
    }
  }
}`

myObj = JSON.parse(myObj)
const path = []
let pathFound = false
findPath(myObj, 'car')

function findPath (obj, objKey) {
  for (const key in obj) {
    if (key === objKey) {
      pathFound = true
      return path.push(key)
    }
    if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
      path.push(key)
      findPath(obj[key], objKey)
    }
  }
  if (!pathFound) {
    path.pop()
  }
}
console.log(path)
cWerning
  • 583
  • 1
  • 5
  • 15
0

I wouldn't recommend writing your own code to iterate JSON (because then you have to maintain it, and you'll probably write it wrong, and then other people will have to debug it).

Use a library, such as flat.

Then create some tiny, easily testable utility functions, that get you what you want from that library.

import flat from 'flat';

const yourJson = {
  "address": {
    "city": {
      "type": "string"
    },
    "country": {
      "type": "string"
    },
    "county": {
      "type": "string"
    },
    "street": {
      "car": {
        "type": "string"
      },
      "type": "string"
    }
  }
}

const getPath = (json,matcher,transform) => {
   const flattened = flat(json);
   return transform(Object.keys(flattened).find(matcher));
}

// use it like this
console.log(
   getPath(
     yourJson, // your json
     (key) => key.match(/car/), // a matcher function that matches a specific key - in this case, the key must end in `car`
     key => key?.replace(/car(.*)$/,'car') // strip everything after the path that you matched, that you aren't interested in
   )
); // logs `address.street.car`

// super short and sweet version
const getPathForKey = (json,key) => {
  const flattened = flat(json);
  const found = Object.keys(flattened).find(k => k.match(new RegExp(key));
  return found ? found.replace(new RegExp(`${key}(.*)$`),key) : undefined;
}

Yes, I realize this isn't "perf" perfect, but it's a "good enough" solution in 97% of cases.

Adam Jenkins
  • 51,445
  • 11
  • 72
  • 100