I have a fetch function which returns a json file. The source file looks like this:
{
"pages":[
{
"page": "people.html",
"title": "People"
},
{
"page": "client.html",
"title": "Client"
}
]
}
When the response from the fetch (after applying .json()) it is a array of multiple objectives, each with two strings:
0
title: "People Policies"
page: "people.html"
1
title: "Client Policies"
page: "client.html"
where 0 and 1 are OBJECTS and title/page the strings.
Question: how can I extract the objects into a simple array (not objects) with multiple key pairs or is there another way to format the source file?
There are plenty of questions on here with similar questions but I just can't get any of them to work, including Object.entries(obj)
Thanks.
From what I understood from your question is that your source data is an array of objects each having two string values. And after .json(), you're getting an indexed object like
{
0: {
// ....
}
}
In this case, you can try Object.values() like
fetch(some_url).then(resp => resp.json()).then(resp => {
// resp is your object
let formattedArray = Object.values(resp);
console.log(formattedArray)
})
const data = {
"pages":[
{
"page": "people.html",
"title": "People"
},
{
"page": "client.html",
"title": "Client"
}
]
}
const pages = data.pages.map(obj => obj.pages)
const titles = data.pages.map(obj => obj.title)
Not sure which one you wanted in an array so heres both.
const json = {
"pages":[
{
"page": "people.html",
"title": "People"
},
{
"page": "client.html",
"title": "Client"
}
]
}
const addObj = json.pages
for (el of json.pages) {
console.log('key-value pairs:', Object.entries(el), '; keys:', Object.keys(el), '; values:', Object.values(el))
}
Related
I am an old-school C++ programmer - trying to get to grips with Postman, JSON, REST APIs, etc, and struggling..
I am trying to write a Postman test to visualize some JSON response data - which I would like to show in a table format with some merged key names as column headings.
The problem is that the number of data items in a response can vary and the key names can also vary - depending on the input parameters.
So say, for the following JSON which has two data items:
{
"data": [
{
"input": [
{
"value": "ABC",
"identifierType": "a1"
}
],
"output": [
{
"value": "BT",
"identifierType": "b1",
"name": "BT GROUP",
"status": "Active",
"classification": "Ordinary"
}
]
},
{
"input": [
{
"value": "BCD",
"identifierType": "a1"
}
],
"output": [
{
"value": "EFG",
"identifierType": "b1",
"name": "SIEMENS",
"status": "Active",
"classification": "Ordinary"
}
]
}
]
}
I want to end up with a collection containing column headings that looks something like this:
[“Input value”, “Input identifierType”,“Output value”,“Output identifierType”,“Output name”,“Output status”,“Output classification”]
I can get part of the way with something like the following:
function parseData(response, host) {
const results = response.map(elem => (
[
elem.input[0].value,
elem.input[0].identifierType,
elem.output[0].value,
elem.output[0].identifierType,
elem.output[0].name,
elem.output[0].status,
elem.output[0].classification,
]
));
const headers = [];
for (const key in response[0].input[0]){
headers.push(`Input ${key}`)
}
for (const key in response[0].output[0]){
headers.push(`Output ${key}`)
}
return [results, headers]
}
This gives me the desired headers: [“Input value”, “Input identifierType”,“Output value”,“Output identifierType”,“Output name”,“Output status”,“Output classification”]
However, I want to make this more general i.e. not have to specify input[0] and output[0] in the for loops - as these key names could differ for different query responses.
I did ask this question on the Postman forums and someone helpfully provided a code snippet that allows me to extract the 'input' and 'output' names.
for (const _outer in response[0]) {
for (const _inner in _outer) {
for (const key in _inner) {
headers.push(`${_outer} ${key}`)
}
}
}
But that only gives me: ["input 0", "input 0", "input 0", "input 0", "input 0", "output 0' …] for the headers. For some reason I cannot access the inner keys such as value, name, identifierType, status etc
Can someone please suggest where the above is going wrong / how to get what I am after?
Thanks.
Ok - I managed to get an answer on the Postman Forums - thanks.
the solution is:
for (const outerkey in response[0]){
for (const innerkey in response[0][`${outerkey}`][0]){
headers.push(`${outerkey} ${innerkey}`)
}
}
and gave me:
"input value", "input identifierType", "output value", "output identifierType", "output name", …]
UPDATE: The data items extraction was still hardcoded with key names (e.g. elem.input[0].identifierType and so), so I replaced that also to give the following solution:
function parseData(response, host) {
const results = response.map(function(val, index){
temp = [];
for (const outerkey in val){
for (const innerkey in val[`${outerkey}`][0]){
temp.push(val[`${outerkey}`][0][`${innerkey}`]);
}
}
return temp
}
);
const headers = [];
for (const outerkey in response[0]){
for (const innerkey in response[0][`${outerkey}`][0]){
headers.push(`${outerkey} ${innerkey}`)
}
}
return [results, headers]
}
I have the following object below with multiple arrays.
{
"services": [
{
"id": "100",
"name": "PIX"
},
{
"id": "200",
"name": "Rendimentos"
}
],
"channels": [
{
"id": "300",
"name": "Chat"
}
]
}
The idea is to generate query strings, something like that.
services=100&services=200&channels=300
I know you can do it with map and join, but I would know if it was with a pure object, now this format below, I'm confused
You can use URLSearchParams() API.
Iterate your data and append key/value pairs or map an entries array to pass to the constructor
I have no idea what determines the expected output you have shown from the data displayed so am using a simpler data structure for demonstration purposes.
You can combine with URL() API to create full url string as shown below also
const data = [
{name:'foo', value:10},
{name:'bar', value:20}
]
// Loop and append key/values
const params = new URLSearchParams();
data.forEach(e => params.append(e.name, e.value));
console.log('params:', params.toString());
// Alternate approach passing entries array to constructor
const params2 = new URLSearchParams(data.map(e => [e.name,e.value]));
console.log('params2:',params2.toString())
//Adding to a URL
const url = new URL('http://example.com')
url.search = params
console.log('Full url:',url)
Using the updated array data in question:
const data={services:[{id:"100",name:"PIX"},{id:"200",name:"Rendimentos"}],channels:[{id:"300",name:"Chat"}]};
const entries = [];
Object.entries(data).forEach(([k,arr])=> arr.forEach(({id}) => entries.push([k,id])));
const params = new URLSearchParams(entries);
const url = new URL('http://example.com')
url.search = params;
console.log(url)
Looks like you're hung up on trying to iterate an object with map() or join(), which you can't do directly. Instead you can use Object.entries to convert the object into an array and iterate that. Since there is a nested map() you can flat() it before join()
let obj = {
"services": [{
"id": "100",
"name": "PIX"
},
{
"id": "200",
"name": "Rendimentos"
}
],
"channels": [{
"id": "300",
"name": "Chat"
}]
}
let queryString = Object.entries(obj).map(s => s[1].map(e => `${s[0]}=${e.id}`)).flat().join('&')
console.log(queryString)
I have the following array with multiple arrays inside the object, how do I generate a query string, where the output should be.
Where services and accountTypes for example that are entries from array it becomes a key in query string.
The value in query string is the id from object in each array
Output should be for example
services=10&services=30&accountTypes=20
Array
[
{
"services": [
{
"id": "10",
"name": "PIX"
},
{
"id": "30",
"name": "Income"
},
],
"accountTypes": [
{
"id": "20",
"name": "Digital Account"
}
]
}
]
My function that I tried.
I tried it with the encodeURIComponent as below, but it's generating undefined
const params = initialFilterDataJson.map((param: QueryParamsType) => {
return encodeURIComponent(param.key) + '=' + encodeURIComponent(param.id)
})
const queryString = params.join('&')
http://localhost:3000/api/accounts?undefined=undefined
Your code is not nesting deep enough in the data structure. You need to have nested loops, first to visit the objects in the outer array, then to visit the keys (with corresponding arrays) of such an object, and then to visit each inner object in such an array:
const initialFilterDataJson = [{"services": [{"id": "10","name": "PIX"},{"id": "30","name": "Income"},],"accountTypes": [{"id": "20","name": "Digital Account"}]}];
const queryString = initialFilterDataJson.flatMap((param) =>
Object.entries(param).flatMap(([key, arr]) =>
arr.map(({id}) => encodeURIComponent(key) + '=' + encodeURIComponent(id))
)
).join('&');
console.log(queryString);
Side note: some web servers can deal better with duplicate keys in the query string when they are suffixed with [], like services[]=10&services[]=20.
I'm using Typescript with TypeORM. Using CreateQueryBuilder, I want to receive a nested object. Instead I'm receiving a single flat object as represented in block number two. How can I fix this?
const x = await getConnection()
.createQueryBuilder()
.select(['reportHead', 'order', 'workOrder'])
.from('report_head', 'reportHead')
.innerJoin('reportHead.workOrder', 'workOrder')
.innerJoin('workOrder.order', 'order')
.where(`order.customer.id = :customerId`, { customerId: req.user.customer.id })
.execute();
How can I avoid the data looking like this:
{
"reportHead_id": "asd",
"reportHead_number": "123",
"workOrder_id": "dsa",
"workOrder_status: "OK",
"order_id": "sda",
"order_whatev": "ks"
}
but rather have a neste object like this:
{
"reportHead": {
"id": ...
},
"workOrder": {
"id": ...
},
"order": {
"id": ...
}
}
The solution was to not use .execute(), but rather .getMany().
I want to fetch all the names and label from JSON without loop. Is there a way to fetch with any filter method?
"sections": [
{
"id": "62ee1779",
"name": "Drinks",
"items": [
{
"id": "1902b625",
"name": "Cold Brew",
"optionSets": [
{
"id": "45f2a845-c83b-49c2-90ae-a227dfb7c513",
"label": "Choose a size",
},
{
"id": "af171c34-4ca8-4374-82bf-a418396e375c",
"label": "Additional Toppings",
},
],
},
]
}
When you say "without loops" I take it as without For Loops. because any kind of traversal of arrays, let alone nested traversal, involve iterating.
You can use the reduce method to have it done for you internally and give you the format you need.
Try this :
const data = {
sections: [
{
id: "62ee1779",
name: "Drinks",
items: [
{
id: "1902b625",
name: "Cold Brew",
optionSets: [
{
id: "45f2a845-c83b-49c2-90ae-a227dfb7c513",
label: "Choose a size"
},
{
id: "af171c34-4ca8-4374-82bf-a418396e375c",
label: "Additional Toppings"
}
]
}
]
}
]
};
x = data.sections.reduce((acc, ele) => {
acc.push(ele.name);
otherName = ele.items.reduce((acc2, elem2) => {
acc2.push(elem2.name);
label = elem2.optionSets.reduce((acc3, elem3) => {
acc3.push(elem3.label);
return acc3;
}, []);
return acc2.concat(label);
}, []);
return acc.concat(otherName);
}, []);
console.log(x);
Go ahead and press run snippet to see if this matches your desired output.
For More on info reduce method
In the context of cJSON
yes, we can fetch the key value for any of the object.
1 - each key value is pointed by one of the objects. will simply fetch that object and from there will get the key value.
In the above case for
pre-requisition: root must contain the json format and root must be the cJSON pointer. if not we can define it and use cJSON_Parse() to parse the json.
1st name object is "sections" will use
cJSON *test = cJSON_GetObjectItem(root, "sections");
char *name1 = cJSON_GetObjectItem(test, "name" )->valuestring;
2nd name key value
cJSON *test2 = cJSON_GetObjectItem(test, "items");
char *name2 = cJSON_GetObjectItem(tes2, "name")->valuestring;
likewise, we can do for others as well to fetch the key value.