-2

I am trying to apply filter on all urls within json object. Is to possible to apply a filter on specific key value in entire object?

For Example

   json ={
    "items":
        {
            "item":
                [
                    {
                        "id": "0001",
                        "url": "assets/img/abc.png",
                        "name": "Cake",
                        "ppu": 0.55,
                        "batters":
                            {
                                "batter":
                                    [
                                        { "id": "1001", "url": "assets/img/abc.png" },
                                        { "id": "1002", "url": "assets/img/abc.png" },
                                        { "id": "1003", "url": "assets/img/abc.png" },
                                        { "id": "1004", "url": "assets/img/abc.png" }
                                    ]
                            },
                        "topping":
                            [
                                { "id": "5001", "url": "assets/img/abc.png" },
                                { "id": "5002", "url": "assets/img/abc.png" },
                                { "id": "5005", "url": "assets/img/abc.png" },
                                { "id": "5007", "url": "assets/img/abc.png" },
                                { "id": "5006", "url": "assets/img/abc.png" },
                                { "id": "5003", "url": "assets/img/abc.png" },
                                { "id": "5004", "url": "assets/img/abc.png" }
                            ]
                    }

                ]
        }
}

I want to replace all url values into file name; assets/folder/ppp.png > ppp.png

so, result should be like,

    Resultjson = {
    "items":
        {
            "item":
                [
                    {
                        "id": "0001",
                        "url": "abc.png",
                        "name": "Cake",
                        "ppu": 0.55,
                        "batters":
                            {
                                "batter":
                                    [
                                        { "id": "1001", "url": "abc.png" },
                                        { "id": "1002", "url": "abc.png" },
                                        { "id": "1003", "url": "abc.png" },
                                        { "id": "1004", "url": "abc.png" }
                                    ]
                            },
                        "topping":
                            [
                                { "id": "5001", "url": "abc.png" },
                                { "id": "5002", "url": "abc.png" },
                                { "id": "5005", "url": "abc.png" },
                                { "id": "5007", "url": "abc.png" },
                                { "id": "5006", "url": "abc.png" },
                                { "id": "5003", "url": "abc.png" },
                                { "id": "5004", "url": "abc.png" }
                            ]
                    }

                ]
        }
}

I have tired some filters, but it doesn't apply on entire object.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
Jeet
  • 13
  • 1
  • 5

3 Answers3

1

Your "json" wasn't written correctly. Also json is just a format, what you're working with is a javascript object/array.

Your data structure should look like this:

const data = [{
    "url": "assets/folder/abc.png",
    "type": "None"
  },
  {
    "url": "assets/folder/xyz.png",
    "type": "None"
  },
  {
    "more": [{
        "url":"assets/folder/sss.png",
        "type": "None"
      },
      {
        "url": "assets/folder/ppp.png",
        "type": "None"
      }
    ]
  }
]

Solution using Array#map, String#split, Array#pop

const data=[{"url":"assets/folder/abc.png","type":"None"},{"url":"assets/folder/xyz.png","type":"None"},{"more":[{"url":"assets/folder/sss.png","type":"None"},{"url":"assets/folder/ppp.png","type":"None"}]}]

function rHandler(arr){
  return arr.map(({more, url, type})=>{
     if(more){
      return {more: rHandler(more)}
     }
     
     return {url: url.split('/').pop(), type};
  });
}

const res = rHandler(data);
console.log(res);
kemicofa ghost
  • 16,349
  • 8
  • 82
  • 131
  • Input json may not be an array. and structure could be anything, not map,more and url only. I only need url, it could be anywhere inside the object – Jeet Jul 25 '19 at 10:15
1

So assuming you are not using ES6, and that other solutions teach you how to change the value using maps but you need to "apply a filter on specific key value in entire object"

If you have this structure:

var more= [{"assets/folder/sss.png", "type": "None" },
                 {"assets/folder/ppp.png", "type": "None" }]
    ];
var formatted = more.map(function(item) {
  var formattedItem= {}
  // map every key
  Object.keys(item).forEach(function(key) {
    if(key !=== 'type'){
       // create a new key removing the part you don't need and assign the previous value to it
       formattedItem[key.split('/').pop()] = item[key];
    } else {
      formattedItem[key] = item[key];
    }
  });
  return formattedItem;
});

Update

Since the real json was updated, not the initial question, the problem you are trying to solve is that you need a recursive function to iterate over the tree of objects, read this question:

function iterate(obj) {
    Object.keys(obj).forEach(function (key) {
        if (Array.isArray(obj[key])) {
            obj[key].forEach(function (subObj) {
                iterate(subObj);
            });
        }
        else if (typeof obj[key] === "object") {
            iterate(obj[key]);
        }
        else if (key === 'url') {
            obj[key] = obj[key].split('/').pop();
        }
    });
}
georgeawg
  • 48,608
  • 13
  • 72
  • 95
0

First you need to fix your input:

const json = [{"url": "assets/folder/abc.png", "type": "None" },
              {"url": "assets/folder/xyz.png", "type": "None" },
              {"more": [{"url": "assets/folder/sss.png", "type": "None" }],
              {"url": "assets/folder/ppp.png", "type": "None" }]

Then you can do smth like:

const formattedOutput = json.map(obj => {
  if (obj.more) {
    return {
      ...obj,
      more: obj.more.map(nestedObj => ({
        ...nestedObj,
        url: nestedObj.url.replace("assets/folder/", "")
      }))
    };
  } else {
    return { ...obj, url: obj.url.replace("assets/folder/", "") };
  }
});
Clarity
  • 10,730
  • 2
  • 25
  • 35
  • thanks, I just updated the example json. Here in JSON `more:` can be any key or keys. I need to find value of urls and apply basename(nodejs) function to replace url with filename. – Jeet Jul 25 '19 at 09:48