loop through simple json object - json

how do I loop through this json object to get each item value? I know this is easy but I need to undestand why there is two brackets ([]) in the first and end of this json object.
[// I'm talking about this
[
{
"id": 2,
"title": "xxxxxxxxx",
"author": "mike123",
"postdate": "March 12, 2013 at 6:46 pm",
"postdatecreation": "2013-03-12",
"posteditdate": null,
"postcontent": "eeeeee",
"userID": 34
}
]
]// and this
if I remove them the json still remain valid.

you can loop through your json object using $.each loop. here is the fiddle:
http://jsfiddle.net/Ay2UB/
here results is an array of array of an object. i've passed that object by accessing index
results[0] will give you an array
results[0][0] will give you object
code below:
var results=[
[
{
"id": 2,
"title": "xxxxxxxxx",
"author": "mike123",
"postdate": "March 12, 2013 at 6:46 pm",
"postdatecreation": "2013-03-12",
"posteditdate": null,
"postcontent": "eeeeee",
"userID": 34
}
]
]
$.each(results[0][0],function(key, value){
alert(value);
});
$.each can be used to loop through array or objects follow below link for more information:
http://api.jquery.com/jQuery.each/
Hope it helps. please correct me if I'm wrong.

Related

What is the standard format for returning lists in REST JSON responses?

When returning a list of objects in a JSON response, say a GET request to a /movies endpoint, is it more common to return a JSON array or an object that wraps a JSON array? I've seen both formats in APIs and I was wondering if the standard. If there isn't, which way is preferable?
i.e.
[
{
"name": "Harry Potter",
"year": 2000
}
]
vs.
{
"movies": [
{
"name": "Harry Potter",
"year": 2000
}
]
}
In general if you have a service that only return a list, the first option is perfect fine:
[
{
"name": "Harry Potter",
"year": 2000
}
]
But if you are thinking in a general way to do it will be better add more context data, as total items counter, pagination variables or status values. So in spite of the first one is perfectly fine, I always prefer the second one, but without the name of the collection/array/table name and with more context info, as for example:
{
"items": [
{
"name": "Harry Potter",
"year": 2000
}
],
"total": 1,
"page": 1,
"pages": 1
"status": 1,
"timestamp: 121344
}
Set the array nested on movies value is a bit redundant. But for my it's only a practical approach that for my experience is more readable and used in all projects which I am related.

Parsing non consistent json response length in excel vba

Using VBA-JSON v2.0.1 in excel VBA
Here is the JSON response I get from API query
{
"currency": {
"code": "USD",
"name": "US Dollar",
"prefix": "$",
"postfix": null
},
"products": [
{
"product_id": xxxxx,
"model_code": "xxxxx",
"quantity": 1,
"price": "45.60",
"total": "45.60",
"retail_price": "63.84"
}
],
"shipping": [
{
"name": "UPS",
"price": 43.83,
"delivery": "3 -10 Days delivery"
},
{
"name": "DHL",
"price": 20.29,
"delivery": "2-6 days"
},
{
"name": "FedEx",
"price": 31.46,
"delivery": "2-6 days"
},
{
"name": "EMS",
"price": 25.74,
"delivery": "7 - 25 Days delivery"
},
{
"name": "Air Mail",
"price": 11.85,
"delivery": "10 - 25 Days delivery"
}
]
}
Here is a part of my code to parse the price from "Air Mail" element.
result = objHTTP.responseText
Dim Json As Object
Dim resultAirmailprice As String
Set Json = JsonConverter.ParseJson(result)
resultAirmailprice = Json("shipping")(5)("price")
Cells(2, 2).Value = resultAirmailprice
The code runs fine when the "Air Mail" element is in (5) of "shipping" element. The problem is sometimes there are no "UPS" and "Air Mail" elements, so I got an error.
How to write code to parse the "Air Mail" price and if not exists, parse from "EMS" price(or the cheapest price out of all)?
Looking at Json parser code, it returns a Dictionary Object that contains other Dictionary Objects (sub keys) and, for arrays, Collection Objects. In the Json I see that "shipping" is an array and so the parser returns a Collection Object.
So you can use all the Collection members and methods to manipulate and access it. In particular, you can use Json("shipping").Count to check how many elements the Shipping collection has. Or you can iterate over the collection with For each x in Json("shipping").
To check whether you have a Dictionary or a Collection, you could use the TypeName function or the TypeOf..Is operator.

Jmeter aggregate certain response values from json to use in next request

I have the following response coming from a request
[
{
"id": 3767,
"sellerName": "abc",
"siteActivity": [
{
"siteId": -1,
"siteName": "example.com",
"categories": [
{
"categoryId": 79654,
"parentId": null,
"name": "Photo & Picture Frames",
"siteName": null,
"channelType": null
},
{
"categoryId": 114397,
"parentId": null,
"name": "Chests of Drawers",
"siteName": null,
"channelType": null
},
{
"categoryId": 11707,
"parentId": null,
"name": "Jewellery Boxes",
"siteName": null,
"channelType": null
},
{
"categoryId": 45505,
"parentId": null,
"name": "Serving Trays",
"siteName": null,
"channelType": null
}
]
}
]
},
{
"id": 118156,
"sellerName": "xyz",
"siteActivity": [
{
"categoryId": 45505,
"parentId": null,
"name": "Serving Trays",
"siteName": null,
"channelType": null
}
]
}
]
Now, I need to extract "id" values and "categoryId" values and send them as list in the next request body.
Currently, I am using JSON Path Extractor with the expression
$.[*].id
to get my hand on all ids and
$.[*].siteActivity.[categoryId]
for category ids.
Next, I want to use the above values and send them as parameters in request body.
Currently, I am able to extract only one id with
$.[0].id
and then assigning it to variable "id" and using the following in request body
{"ids":[{"id":"${id}"}]}
but I want to be able to send
{"ids":[{"id":"${id}"},{"id":"${id2}"}....]}
There is no limit on how many ids can be there, so I cannot hardcode and need something dynamic to do the aggregation. What kind of processor can help me here? Please add some example if you can.
I believe that you should be able to use Beanshell PostProcessor for building the request.
Given your sample data your $.[*].id JSONPath Expression should return the following values:
id=[3767,118156]
id_1=3767
id_2=118156
So basically you need to:
Determine "id" count
Populate dynamic JSON Object to send
Store it to JMeter variable for later use
In order to do so add a Beanshell PostProcessor after JSONPath Extractor and put the following code into its "Script" area
import net.sf.json.JSONArray;
import net.sf.json.JSONObject; // necessary imports
JSONObject data2Send = new JSONObject();
JSONArray array = new JSONArray(); // instantiate JSON-related classes
int idCount = vars.get("id").split(",").length; // get "id" variables count
for (int i = 1; i <= idCount; i++) { // for each "id" variable
JSONObject id = new JSONObject(); // construct a new JSON Object
id.put("id", vars.get("id_" + i));// with name "id" and value id_X
array.add(id); // add object to array
}
data2Send.put("ids",array); // add array to "ids" JSON Object
vars.put("myJSON", data2Send.toString()); // store value as "myJSON" variable
You can refer to your {"ids":[{"id":"3767"},{"id":"118156"}]} data as ${myJSON} where required.
The approach will play for any number of "id" variables.
References:
Welcome to Json-lib
How to use json-lib
Json-lib JavaDoc
How to use BeanShell: JMeter's favorite built-in component

typeahead nested json object

I am new to Ember and JSON. I want to parse a JSON object that is below with typeahead library
and access nested object values by searching their keys.
I have this Json format:
return [
{
"id": 1,
"category_name": "Supermarket",
"category_description": "SUPER MARKET",
"image_url": "",
"merchants": [
{
"name": "CARREFOUR",
"id": 12,
"merchant_type_id": 1,
"merchant_type_description": "Gold",
"merchant_redeption_rate": 0.002500,
"image_url": "https://jpg",
"branches": [
{
"id": 123456,
"latitude": 37.939483,
"area": "ΑΓ. ΔΗΜΗΤΡΙΟΣ",
"zip": "12345"
},
{
"id": 4567890,
"longitude": 23.650622,
"area": "ΑΓ. ΙΩΑΝΝΗΣ ΡΕΝΤΗΣ",
"zip": "12345"
}
]
},
{
"name": "CAFCO",
"id": 13,
"merchant_type_id": 3,
"merchant_type_description": "None",
"merchant_redeption_rate": 0.002500,
"image_url": "https:.jpg",
"branches": [
{
"id": 127890,
"latitude": 38.027870,
"area": "ΠΕΡΙΣΤΕΡΙ",
"zip": "12345"
}
]
}
]
},
{
"id": 2,
"category_name": "Πολυκαταστήματα",
"category_description": "ΠΟΛΥΚΑΤΑΣΤΗΜΑ",
"image_url": "",
"merchants": [
{
"name": "AGGELOPOYLOS CHR.",
"id": 15,
"merchant_type_id": 2,
"merchant_type_description": "Silver",
"merchant_redeption_rate": 0.002500,
"image_url": "https://www.nbg.gr/greek/retail/cards/reward-programmes/gonational/PublishingImages/aggelopoulos.jpg",
"branches": [
{
"id": 234780,
"latitude": 35.366118,
"longitude": 24.479461,
"address": "ΕΘΝ. ΜΑΚΑΡΙΟΥ 9 & ΕΛ. ΒΕΝΙΖΕΛΟΥ 1",
"area": "Ν. ΦΑΛΗΡΟ",
"zip": "12345"
}
]
}
]
}
];
--------------------------Updated----------------------------
For example, i want to search using typeahead the name of merchants and when the letter we write to search matches the name of merchants it will appear the corresponding category_name and backwards.
Example -> when i keyboard the s it will appear :
Category : Supermarket,
Name: CARREFOUR
Name: CAFCO
And the same output on the dropdown of search when i keyboard the letter c.
Any help?
New Jsbin example
The simplest way (in my mind) to get this to work is to create a computed property that will contain an array of latitudes. But how do we get there?
To get to latitude, you need to go through array of merchants and then array of branches. Being that this will be across multiple elements, you are going to end up with "array of arrays" type data structure, which is annoying to deal with. So, to simplify this, we can create a simple flatten function as follows:
flatten: function(origArray){
var newArr = [];
origArray.forEach(function(el) {
el.forEach(function(eachEl){
newArr.push(eachEl);
});
});
return newArr;
},
In addition to our function above, Ember already provides us with many other useful functions that can be used on arrays (see here). One of those is mapBy(property) which transforms an array into another array only keeping the values of the property we specified.
So, to create a lats (for latitudes) property, we can just do this:
lats: function(){
var merchantsArr = this.get('model').mapBy('merchants');
merchantsArr = this.flatten(merchantsArr);
var branchesArr = merchantsArr.mapBy('branches');
branchesArr = this.flatten(branchesArr);
return branchesArr.mapBy("latitude").compact();
}.property('model')
Above, I am basically using mapBy, flatten (see above) and compact which
Returns a copy of the array with all null and undefined elements removed.
Once you have the lats property with all the necessary data, the rest is easy.
Your call to component becomes:
{{x-typeahead data=lats name='category_name' selection=myColor}}
Note lats instead of model you originally were passing into the component.
And now, to access the value of data property in the component, you do
`this.get('data')`
which you can just pass in as the source like so:
source: substringMatcher(self.get('data'))
Working solution here
Update
Updating my answer based on your updated question.
OK, so this is getting a little more complicated. You now need more than just one property (latitude) from the object. You need category_name and merchant name.
In addition to mapBy, which just grabs one property out of array, Ember also has map which lets you transform the array into pretty much anything you want to:
lats: function(){
var merchantsArr = this.get('model').map(function(thing){
var category_name = thing.category_name;
return thing.merchants.map(function(merchant){
return {
"name": merchant.name,
"category": category_name
};
});
});
merchantsArr = this.flatten(merchantsArr);
return merchantsArr;
}.property('model')
The code above looks complicated, but it's basically just returning an array of top level objects' merchants accompanied by category_name. Since this is an array of arrays, we will need to flatten it.
Then, inside the component, we need to keep in mind that we are not just passing in an array of strings, but rather we are passing in an array of objects. Therefore, we need to look through object's properties (name and category) for a match
$.each(strs, function(i, str) {
if (substrRegex.test(str.name) || substrRegex.test(str.category)) {
matches.push(str);
}
});
Lastly, to actually display both category and merchant name, you need to tell Typeahead how to do that:
templates: {
suggestion: Handlebars.compile('<p>{{name}} – {{category}}</p>')
}
Working solution here

Use $resource of AngularJS to find specific element in json Array

I am new to AngularJS. Trying to get specific element from a JSON array via $resource.
The structure of JSON file staffs.json is like:
[{
"id": 0,
"facility_id": [0],
"name": "Tim",
"role_id": 0
},
{
"id": 1,
"facility_id": [0],
"name": "Duncan",
"role_id": 0
},
{
"id": 2,
"facility_id": [0],
"name": "Tony",
"role_id": 1
},
{
"id": 3,
"facility_id": [0],
"name": "Parker",
"role_id": 1
},
{
"id": 4,
"facility_id": [0],
"name": "Manu",
"role_id": 2
},
{
"id": 5,
"facility_id": [0],
"name": "Ginobili",
"role_id": 2
},
{
"id": 6,
"facility_id": [0],
"name": "Tiago",
"role_id": 3
},
{
"id": 7,
"facility_id": [0],
"name": "Splitter",
"role_id": 3
}]
I am trying to get a staff whose name is "Tiago".
The code is:
var url = 'data/staffs.json';
var username = 'Tiago';
users = $resource(url);
users.get({name: username}, function(data){
alert(data.name);
});
It seems the alert() function inside the get() never gets called. However if I changed the method from users.get() to users.query(), it can get the list of the staffs. I guess this is because the data inside the JSON file is an array, so the query() which is used to get array works, while the get() does not work because it is not for array operation. Am I correct?
I am just wondering if I have to use query() get the whole array and match the elements one by one until I find the one with the same name, or there are some simpler ways to get the element I want.
Thanks
AngularJS resource has a separate query function to avoid JSONP vulnerability for arrays. You have two options:
get all and find the element in the array on the client side
add extra API endpoint for single user and fetch it by the name
I vote for option two, since you don't have to send everything over the wire and you use server (DB) to get the specific user. Server software is optimised for that.
Your best bet would by fetching data with the query() method, then using indexOf()
var url = 'data/staffs.json';
var username = 'Tiago';
users = $resource(url);
users.get({name: username}, function(data){
dataOfMyUser = data.map(function(cur) { return cur.name }).indexOf(username);
alert(dataofMyUser);
});