0

Been delivered some confusing JSON data with a problem I haven't seen before.

The JSON is formatted similar to this structure:

[
  {
    "title": "Event",
    "start_date": "2022-08-20 15:00:00",
    "end_date": "2022-08-20 16:00:00",
    "branch": {
      "85": "branchname"
    },
    "room": {
      "156": "roomname"
    },
    "age_group": {
      "5": "Youth",
      "6": "Teen"
    }
  },
  {
    "title": "Event02",
    "start_date": "2022-08-20 15:00:00",
    "end_date": "2022-08-20 16:00:00",
    "branch": {
      "72": "branchname"
    },
    "room": {
      "104": "roomname02"
    },
    "age_group": {
      "5": "Youth",
      "6": "Teen"
    }
  }
]

I'm trying to pull roomname out of the data, but it's nested in an object that has a random index number. If I manually put in the index number, I can retrieve the data, but the number changes every entry.

If I can figure out how to retrieve the number and store it in a variable, then use it again, or just somehow wildcard to just show any child of any key under the parent node "room" it would work perfect, but I don't know of a way to do this in javascript.

I'm limited to vanilla javascript, no external libraries or jquery.

here is the code that will output correctly if I manually enter the index numbers, but it only works for a single entry.

<script>
    const url = 'example.json';
    fetch(url) 
        .then((response) => { 
            return response.json(); 
        }) 
        .then((json) => { 
            json.map(function(event) { 
                console.log(`${event.start_date}`);
                console.log(`${event.title}`);
                console.log(`${event.room[156]}`);
                return element;
            });
    }, 80);

</script>

EDIT: Forgot to point out, there is always only 1 entry in the "room" tag, but it's index is randomized, so if you just select the room tag it returns undefined or invalid. If I could wildcard the index so it just tries them all, or somehow retrieve the index number and store it in a variable, it would fix the issue.

niceman
  • 2,653
  • 29
  • 57
Sam
  • 65
  • 8
  • `roomname` has a number suffix sometimes like `roomname02`, are you looking for a value which starts with the word `roomname`? – niceman Aug 19 '22 at 18:22
  • related: https://stackoverflow.com/questions/983267/how-to-access-the-first-property-of-a-javascript-object – niceman Aug 19 '22 at 18:25
  • Is it possible to get the data changed on the backend to something like `{"room": { "number": 104, "name": "roomname02" } }`? It would make life a little easier, and make a bit more sense. – Andy Aug 19 '22 at 18:27
  • @niceman The roomname is just an example. Something closer to the actual data is roomname is something like "Upper Level Conference Room 5" – Sam Aug 19 '22 at 18:30
  • 1
    @Andy I don't have any backend access, i've got what i've got. – Sam Aug 19 '22 at 18:31
  • “I don't have any backend access” so a third-party API? If backend devs are on your team, maybe discuss this with them? – niceman Aug 19 '22 at 18:33
  • Did you try @uditkumar11's answer? Looks good to me. – niceman Aug 19 '22 at 18:36

5 Answers5

1

I think this will work:

Here as you don't know the key so, instead of just guessing, you can use Object.values(JSONObjName) to get the list/array of values in that json.

Here I'm also using optional chaining (?.) to handle the case when the json has no key value pairs.

<script>
    const url = 'example.json';
    fetch(url) 
        .then((response) => { 
            return response.json(); 
        }) 
        .then((json) => { 
            json.map(function(event) {
                const roomName = Object.values(event.room)?.[0];
                console.log(`${event.start_date}`);
                console.log(`${event.title}`);
                console.log(`${roomName}`);
                return {...event, room: roomName};
            });
    }, 80);

</script>
uditkumar01
  • 400
  • 5
  • 11
  • This did it! thank you so much! Only change I made is changed the const to a let as the value will change depending on the room name. I need to read up on Object.values, clearly a blindspot for me. – Sam Aug 19 '22 at 18:46
  • It might be a good idea to change that variable name "json" to "data" as it's no longer JSON. And don't forget to `return data.map` when you do otherwise that array is going nowhere. @Sam – Andy Aug 19 '22 at 19:37
0

As long as you always want the first key you can fetch it like this

room = event.room[Object.keys(event.room)[0]]
Patrick
  • 149
  • 7
0

if you want to get just roomname, you could do Object.values(room)[0] or if you want the index and value you could go for Object.entries(room)[0]

Michael
  • 21
  • 2
  • TypeError: Cannot read properties of undefined (reading 'room') It sees the index value as it's randomized number, not 0, so it returns undefined if it's not the random value – Sam Aug 19 '22 at 18:29
  • Maybe made some progress, using the line: `console.log(Object.values(`${event.room}`)[0]);` it returns an open bracket for each entry: `[` – Sam Aug 19 '22 at 18:37
0
arr?.map(({ room }) => {
    for(let [key, value] of Object.entries(room)) {
        console.log('Random Key : ',key)
        console.log('Roomname : ', value)
        console.log('Using random key : ',room[key])
    }
})

By this way you can find the value of room against the random key.

Or you can try this if it is more relevant to you.

arr.map(({ room }) => {
    for(let key of Object.keys(room)) {
        console.log('Random Key : ',key)
        console.log('Using random key : ',room[key])
    }
})
0

Since you may want to do this for branch as well, here's an alternative solution which uses the object key as a computed property name (aka "dynamic key") to get the value.

And since, in this example it's done more than once, I've added that to a function that you can call in the destructuring assignment.

const data=[{title:"Event",start_date:"2022-08-20 15:00:00",end_date:"2022-08-20 16:00:00",branch:{85:"branchname"},room:{156:"roomname"},age_group:{5:"Youth",6:"Teen"}},{title:"Event02",start_date:"2022-08-20 15:00:00",end_date:"2022-08-20 16:00:00",branch:{72:"branchname02"},room:{104:"roomname02"},age_group:{5:"Youth",6:"Teen"}}];

// Get first key from an object
function getKey(obj) {
  return Object.keys(obj)[0];
}

const out = data.map(obj => {
  
  // Destructure the object and call `getKey` with the
  // object to get its only key, and use that
  // as a computed property to get its value, which 
  // we then relabel e.g. `roomName`
  const {
    branch: { [getKey(obj.branch)]: branchName },
    room: { [getKey(obj.room)]: roomName },
    ...rest
  } = obj;
  
  // Now just return a new object with your new keys/values
  return { ...rest, branchName, roomName };

});

console.log(out);

Additional documentation

Andy
  • 61,948
  • 13
  • 68
  • 95