How to avoid extra nesting in json string - json

I tried to create json string according to syntax from wikipedia. I created json string with the following code:
var data = [];
data.push(
{
"firstName": "John",
"lastName": "Smith",
"isAlive": true,
"age": 27,
});
var addressdata = [];
addressdata.push(
{
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
});
data.push(
{
"address" : addressdata
}
);
The string is correct json string. However, the json structure contains some unnecessary nesting, as shown in the Figures 1 and 2 below. More precisely, there are surplus braces for address block, and the string is also enclosured with brackets instead of braces. So, what am I doing wrong? How can I avoid this unnecessary nesting and get structure as shown in Fig. 3?
Fig. 1
Fig. 2
Fig. 3
The string is generated with jsonData : data, in Ajax request.

You are using a list for the data variable. That's why you get brackets in the beginning and end of the JSON body. To overcome this problem you can declare the whole JSON body in the data variable like:
data = {
"firstname": "test",
(...)
"address": [{
"streetAddress": "test"
(...)
}]
}

Related

How to add a field to an existing JSON in Velocity?

I have a JSON coming from a request body and I'm trying to use VTL to map it by adding an additional field to it. The request body looks like this:
{
"name": "John",
"age": 20,
"address": {
"street": "Albert's Street",
"City": "Test City"
}
}
In AWS, I'm trying to map this request body to have an additional field which is coming from a parameter in the URL path to become this:
{
"name": "John",
"age": 20,
"address": {
"street": "Albert's Street",
"City": "Test City"
},
"operation": "$input.params('path.operation')"
}
I have tried looping through with something like this but it doesn't work very well:
#set($allParams = $input.path('$'))
{
#foreach($type in $allParams.keySet())
#set($params = $allParams.get($type))
"$type" : {
#foreach($paramName in $params.keySet())
"$paramName" : "$util.escapeJavaScript($params.get($paramName))"
#if($foreach.hasNext),#end
#end
}
#if($foreach.hasNext),#end
#end
}
Moreover, this only works for those with 2 levels in the JSON. It doesn't work for those at the first level of the JSON or if I happen to have more than 2 levels in the JSON payload.
All I need is simply appending one more field into the existing request body of a JSON payload. How can I do that in Velocity?
You can add a operation property to the input JSON like this:
#set ($input.path('$').operation = 'example')
$input.json('$')
The above results in the following for your example:
{
"name": "John",
"age": 20,
"address": {
"street": "Albert's Street",
"City": "Test City"
},
"operation": "example"
}
Of course, you can use a value from params instead of 'example'.
By the way, consider running the param through $util.escapeJavaScript for added security.

Usage of rest parameter with object

I am trying to pull the user information by passing some object values as rest parameter. Whenever I try to pass 2 arguments, the code throws an error (undefined). What is it that I am missing?
Here is the Jsfiddle link of what I am trying to do.
let userAddress = [{
"street": "someStreet1",
"house": "1",
"person": "User1"
}, {
"street": "someStreet2",
"house": "2",
"person": "User2"
}, {
"street": "someStreet3",
"house": "3",
"person": "User3"
}];
let userInfo = [];
let addressToCheck = (...newUserHouse) => {
for (let address of userAddress) {
if (newUserHouse == address.house) {
userInfo.push(address.person);
console.log(userInfo);
}
}
}
console.log(addressToCheck(3, 2));
EDIT
Additional info:
I had this problem in which I had a JSON data and I had to pass multiple values and check whether those values were present in the dataset or not and if present, display the whole object.
For example; In the userAddress Array (as shown above) I need to check if 3, 2 (passed as an argument) are present as house number in userAddress. If they are present, then display the whole information about that particular object. As in this case, since 3, 2 are valid house numbers, the expected result should be:
Object { "street": "someStreet2", "house": "2", "person": "User2" }
Object { "street": "someStreet3", "house": "3", "person": "User3" }
The code does not throw an undefined error, it simply logs the value undefined. And that happens because you are calling console.log on the return value of addressToCheck but the function doesn't return a value, so it implicitly returns undefined. See console.log returns an additional undefined.
However, there are more problems with your code. It only accidentally works when you pass a single argument because you are using loose comparison (==).
The value of a rest parameter is always an array. That means you are really doing the following comparisons:
[1, 2] == "1"
[1, 2] == "2"
[1, 2] == "3"
I hope it's obvious why this cannot work. An array with multiple elements cannot be equal to a single "element", so the if condition is never fulfilled.
It works accidentally with a single argument because the string representation of [1] is simply "1". The string representation if [1,2] however is "1,2".
You are not explaining what the desired outcome is but if you want to select all addresses for the provided input, you should be using .filter instead. And you can convert the provided arguments to a set for fast lookup.
Instead of assigning values to an "external" array, simply return the result from the function.
let userAddress = [{
"street": "someStreet1",
"house": "1",
"person": "User1"
}, {
"street": "someStreet2",
"house": "2",
"person": "User2"
}, {
"street": "someStreet3",
"house": "3",
"person": "User3"
}];
let addressToCheck = (...newUserHouse) => {
newUserHouse = new Set(newUserHouse);
return userAddress.filter(address => newUserHouse.has(address.house));
};
console.log(addressToCheck("3", "2"));
A functional way to achieve this using ES6 is to utilize the Array's filter() and includes() methods in a custom function, (namely getUsersMatchingHouseNumbers), as shown in the gist below:
const userData = [{
"street": "someStreet1",
"house": 1,
"person": "User1"
}, {
"street": "someStreet2",
"house": 2,
"person": "User2"
}, {
"street": "someStreet3",
"house": 3,
"person": "User3"
}]
function getUsersMatchingHouseNumbers(userData, ...houseNumbers) {
return userData.filter(({ house }) => houseNumbers.includes(house));
}
console.log(getUsersMatchingHouseNumbers(userData, 1, 3));
Notes
The userData.filter(({ house }) part uses Object destructuring to obtain only the house property/value from each userData object.
The getUsersMatchingHouseNumbers function returns an array of user objects whose house number matches those passed to the function when it is invoked.
In my code, I was missing out the point that rest parameters are an array of parameters and in order to manipulate them, we have to iterate over them too.
let userAddress = [{
"street": "someStreet1",
"house": 1,
"person": "User1"
}, {
"street": "someStreet2",
"house": 2,
"person": "User2"
}, {
"street": "someStreet3",
"house": 3,
"person": "User3"
}]
let addressToCheck = (...houses) => {
for(let house of houses){
for (let user of userAddress) {
if(user.house === house){
console.log(user);
break;
}
}
}
}
console.log(addressToCheck(1, 3));

parsing nested json data - access directly to a member

I have json data like
data = {
"id":1,
"name":"abc",
"address": {
"items":[
"streetName":"cde",
"streetId":"SID"
]
}
}
How can i access directly to the streetName Value ?
Your json is actually invalid. If you have control over the json generation, first change it to this:
data = {
"id": 1,
"name": "abc",
"address": {
"items": [{
"streetName": "cde",
"streetId": "SID"
}]
}
}
Notice the additional braces around streetName and streetId. Then, to access streetName, do this:
var streetName = data.address.items[0].streetName;

Extract value from array of objects in Postman

I want to extract Id value from the array with objects in Postman and then set it as an environment variable. In case JSON response is an object, the following script works, but not with an array of objects (my array has only one object).
var data = JSON.parse(responseBody);
postman.setEnvironmentVariable("userid", data.Id);
JSON response:
[
{
"Id": 1287,
"LastName": "Trump",
"FirstName": "Donald",
"MiddleName": "Von",
"City": "New York City",
"Phone": "66 77 88",
"State": "New York",
"Fax": "111-222-333",
"ReferenceId": "12345",
"Active": false,
"CurrentWorkingSchemeId": null
}
]
If it is an array of objects, then just select the first object using index [0] before grabbing the object's key like this:
var data = JSON.parse(responseBody);
postman.setEnvironmentVariable("userid", data[0].Id);
This works like charm!
Basically what i am doing here is, parse the response and from the data array, take id and save it in postman environment variable.
var jsonData = JSON.parse(responseBody);
for (var i = 0; i < jsonData.data.length; i++) `
{
var counter = jsonData.data[i];
postman.setEnvironmentVariable("schID", counter.id);
}

Appending a key value pair to a json object

This is the json object I am working with
{
"name": "John Smith",
"age": 32,
"employed": true,
"address": {
"street": "701 First Ave.",
"city": "Sunnyvale, CA 95125",
"country": "United States"
},
"children": [
{
"name": "Richard",
"age": 7
},
{
"name": "Susan",
"age": 4
},
{
"name": "James",
"age": 3
}
]
}
I want this as another key-value pair :
"collegeId": {
"eventno": "6062",
"eventdesc": "abc"
};
I tried concat but that gave me the result with || symbol and I cdnt iterate. I used spilt but that removes only commas.
concattedjson = JSON.stringify(JSON.parse(json1).concat(JSON.parse(json2)));
How do I add a key pair value to an existing json object ?
I am working in javascript.
This is the easiest way and it's working to me.
var testJson = {
"name": "John Smith",
"age": 32,
"employed": true,
"address": {
"street": "701 First Ave.",
"city": "Sunnyvale, CA 95125",
"country": "United States"
},
"children": [
{
"name": "Richard",
"age": 7
},
{
"name": "Susan",
"age": 4
},
{
"name": "James",
"age": 3
}
]
};
testJson.collegeId = {"eventno": "6062","eventdesc": "abc"};
Just convert the JSON string to an object using JSON.parse() and then add the property. If you need it back into a string, do JSON.stringify().
BTW, there's no such thing as a JSON object. There are objects, and there are JSON strings that represent those objects.
You need to make an object at reference "collegeId", and then for that object, make two more key value pairs there like this:
var concattedjson = JSON.parse(json1);
concattedjson["collegeId"] = {};
concattedjson["collegeId"]["eventno"] = "6062";
concattedjson["collegeId"]["eventdesc"] = "abc";
Assuming that concattedjson is your json object. If you only have a string representation you will need to parse it first before you extend it.
Edit
demo for those who think this will not work.
const newTestJson = JSON.parse(JSON.stringify(testJson));
newTestJson.collegeId = {"eventno": "6062","eventdesc": "abc"};
testJson = newTestJson;