How to query a json file? - javascript

Here is the file I would like to parse
I receive a file from a webservice in JSON format.
I would like to parse the content in such a way that I display the name of the president from the USA
{
"response": {
"result": {
"Countries": {
"row": [
{
"no": "1",
"FL": [
{
"content": "USA",
"val": "Country"
},
{
"content": "Barack Obama",
"val": "President"
}
]
},
{
"no": "2",
"FL": [
{
"content": "Cuba",
"val": "Country"
},
{
"content": "Raul Castro",
"val": "President"
}
]
}
]
}
}
}
}
The expected output
{ presidents: [
{ "name": "Barack Obama"}
]
}
could you provide a solution using a kind of JSON XPath?

Assuming that you are loading the response into a variable data:
var data = {
"response" : {
"result" : {
"Countries" : {
"row" : [{
"no" : "1",
"FL" : [{
"content" : "USA",
"val" : "Country"
}, {
"content" : "Barack Obama",
"val" : "President"
}
]
}, {
"no" : "2",
"FL" : [{
"content" : "Cuba",
"val" : "Country"
}, {
"content" : "Raul Castro",
"val" : "President"
}
]
}
]
}
}
}
};
You can then filter your data like this:
data.response.result.Countries.row.filter(function (el) {
return (el.FL[0].content == "USA");
})[0].FL[1];
To get to:
{
"content" : "Barack Obama",
"val" : "President"
}
To get the name, simply specify "content"
data.response.result.Countries.row.filter(function(el){
return (el.FL[0].content == "USA");
})[0].FL[1].content;
EDIT 1
One could search a json object like a string.
If we know that the element will have no children, then we could use something like this:
function find(query,obj) {
var str = JSON.stringify(obj);
var start = str.substr(0,str.indexOf(query)).lastIndexOf('{');
var end = str.substr(start,str.length).indexOf('}');
return str.substr(start,end);
}
console.log(find('"content":"USA"',data))

Despite of the age of the question I want to add this answer as reference for future visitors with the same problem:
You can use JSONPath. The page contains a description and an implementation in JavaScript and PHP.

t = {
"response": {
"result": {
"Countries": {
"row": [
{
"no": "1",
"FL": [
{
"content": "USA",
"val": "Country"
},
{
"content": "Barack Obama",
"val": "President"
}
]
},
{
"no": "2",
"FL": [
{
"content": "Cuba",
"val": "Country"
},
{
"content": "Raul Castro",
"val": "President"
}
]
}
]
}
}
}
}
res={};//Here we will store result
for (i in t.response.result.Countries.row) {
// get current country
country = t.response.result.Countries.row[i].FL[0].content;
// get current president
president = t.response.result.Countries.row[i].FL[1].content;
if (country == 'USA') {
res.presidents=[{name:president}];
break;
}
}

Related

Transform JSON array using ES 6 methods

I have the following example of an array format that needs to be transformed.
{ [
{
"condition": "$and",
"children": [
{ "column": "Title", "comparison": "$eq", "columnValue": "1" },
{ "column": "Event Status", "comparison": "$eq", "columnValue": "2" }
]
},
{
"condition": "$or",
"children": [
{
"column": "Issue Description",
"comparison": "$lt",
"columnValue": "3"
},
{ "column": "Number Label", "comparison": "$gte", "columnValue": "4" }
]
}
]}
It needs to be transformed like this...
{
[
{
"$and" : [
{
"Title" : {
"$eq" : "1"
}
},
{
"Event Status" : {
"$eq" : "2"
}
}
]
},
{
"$or" : [
{
"Issue Description" : {
"$lt" : "3"
}
},
{
"Number Label" : {
"$gte" : "4"
}
}
]
}
]
}
I've tried various iterations of map and reduce. Gotten close, but not completely there.
This is in a Vue project. Here is an example of what I tried.
const result = this.parents.map(({ condition, children }) => {
const childArray = children.reduce(
(c, v) => ({
...c,
[v.column]: { [v.comparison]: v.columnValue }
}),
{}
);
childArray.condition = condition;
return childArray;
});
This returns:
[
{
"Title": { "$eq": "1" },
"Event Status": { "$eq": "2" },
"condition": "$and"
},
{
"Issue Description": { "$lt": "3" },
"Number Label": { "$gte": "4" },
"condition": "$or"
}
]
I cannot figure out how to get the "condition" key in the right place.
ES6 computed property names will be a big help, allowing variable expression enclosed in [] square braces to compute a key value...
let inputExpressions = [
{
"condition": "$and",
"children": [
{ "column": "Title", "comparison": "$eq", "columnValue": "1" },
{ "column": "Event Status", "comparison": "$eq", "columnValue": "2" }
]
},
{
"condition": "$or",
"children": [
{
"column": "Issue Description",
"comparison": "$lt",
"columnValue": "3"
},
{ "column": "Number Label", "comparison": "$gte", "columnValue": "4" }
]
}
];
function translateExpression(expression) {
const translateClause = clause => {
return { [clause.column] : { [clause.comparison] : clause.columnValue } };
};
return { [expression.condition] : expression.children.map(translateClause) };
}
let resultExpressions = inputExpressions.map(translateExpression);
console.log(resultExpressions)

How to get the corresponding value from two objects

I have first data object which has a list of cafe, and second data object which has a list of cafe types.
I need find, get and display the corresponding type value from first data object and ID value from second data object.
For example: in list of cafe, I have Pinta with "type" : "3", it means that 3 is Bar from second object.
First object:
{
"list": {
"item": [
{
"ID": "31",
"name": "Staut",
"type": "1",
},
{
"ID": "34",
"name": "Pinta",
"type": "3",
}
]
}
}
And second object:
{
"list": {
"item": [
{
"ID": "1",
"name": "Restaurant",
},
{
"ID": "2",
"name": "Cafe",
},
{
"ID": "3",
"name": "Bar",
}
]
}
}
I can do it with Lodash. It is right, but I can't display it and it uses high memory.
getValues: function() {
_.forEach(CafeJSON.list.item, function(cafeValue) {
_.forEach(TypeJSON.list.item, function(typeValue){
if (cafeValue.type == typeValue.ID) {
console.log("Cafe name is: ", cafeValue.name, "and type is: ", typeValue.name)
}
})
})
}
Result:
I'd simplify the types object down to a object having key value pairs in the form of '3': 'Bar', then loop the items once, overriding the type property's value.
let list = {
"list": {
"item": [{
"ID": "31",
"name": "Staut",
"type": "1",
},
{
"ID": "34",
"name": "Pinta",
"type": "3",
}
]
}
}
let types = {
"list": {
"item": [{
"ID": "1",
"name": "Restaurant",
},
{
"ID": "2",
"name": "Cafe",
},
{
"ID": "3",
"name": "Bar",
}
]
}
}
let typesSimplified = types.list.item.reduce((a, b) => {
a[b.ID] = b.name;
return a;
}, {});
list.list.item.forEach(e => {
e.type = typesSimplified[e.type];
});
console.log(list);

javascript object filter based on multiple conditions

I have the following object and I want to filter it based on some properties and output only some parts of it.
{
"email" : "john.doe#acme.com",
"name" : " John Doe",
"groups" : [
{
"name" : "group1",
"country": "US",
"contacts" : [
{ "localId" : "c1", "address" : "some address 1" },
{ "localId" : "c2", "address" : "some address 2" },
{ "localId" : "c3", "address" : "some address 3" }
]
},
{
"name" : "group2",
"country": "Canada",
"contacts" : [
{ "localId" : "c1", "address" : "some address 1" },
{ "localId" : "c3", "address" : "some address 3" }
]
}
]
}
the result should look like:
{
"email" : "john.doe#acme.com",
"name" : " John Doe",
"groups" : [
{
"name" : "group1",
"country": "US",
"contacts" : [
{
"localId" : "c3",
"address" : "some address 3"
}
]
}
]
}
So my conditions are:
groups.name="group1"
groups.contacts.localId="c3"
how can I achieve it using some ecma6 js function? with the least memory load? I am in nodejs env >=8.9.0.
update:
here is my failing attempt:
const conditions = {"groups.name": "group1", "groups.contacts.localId": "c3"};
let res = mylist.map((i)=>{
return {
email: i.email,
name: i.name,
groupsName: conditions.groups.name
}
})
You can do this fairly succinctly with filter(). If you filter on group name first you won't waste time filtering the contacts:
let obj = {
"email": "john.doe#acme.com",
"name": " John Doe",
"groups": [{
"name": "group1",
"country": "US",
"contacts": [{
"localId": "c1",
"address": "some address 1"
},
{
"localId": "c2",
"address": "some address 2"
},
{
"localId": "c3",
"address": "some address 3"
}
]
},
{
"name": "group2",
"country": "Canada",
"contacts": [{
"localId": "c1",
"address": "some address 1"
},
{
"localId": "c3",
"address": "some address 3"
}
]
}
]
}
let newObj = {
"email": obj.email,
"name": obj.name,
"groups": obj.groups.filter(item => item.name == "group1").map(g => (g.contacts = g.contacts.filter(c => c.localId == "c3"), g))
}
console.log(newObj)
You can use filter and map. If obj is your initial object then you can do:
obj.groups = obj.groups.filter((g)=>g.name==="group1")
for(int i = 0; i < obj.groups.length;i++)
{
obj.groups[i].contacts = obj.groups[i].contacts.filter((c)=>c.localId==="c3"))
}

AngularJS adding and pushing in nested JSON objects

I have a JSON Object like this :
{
"Name": "Shivansh",
"RollNo": "1",
"Stream": "CSE",
"OverallScore": "76",
"Semester": [
{
"SemesterName": "FY-2012 - 1",
"TotalScore": "78.00",
"StartDate" : "2012-02-14",
"EndDate" : "2012-07-16",
"Amount" : "55000",
"Subject": [
{
"subjectname": "maths",
"score": "81"
},
{
"subjectname": "chemistry",
"score": "79"
},
{
"subjectname": "physics",
"score": "77"
}
]
},
{
"SemesterName": "FY-2013-1",
"TotalScore": "76.00",
"StartDate" : "2013-02-16",
"EndDate" : "2014-07-16",
"Amount" : "55000",
"Subject": [
{
"subjectname": "ADA",
"score": "80"
},
{
"subjectname": "Operating System",
"score": "77"
},
{
"subjectname": "Databases",
"score": "73"
},
{
"subjectname": "Economics",
"score": "71"
}
]
}
]
}
Now i want to add another semester field into this JSON by using angularJS. Can anyone help me how to achieve this. The next field that I would add may look like:
{
"SemesterName": "FY-2013-2",
"TotalScore": "75.00",
"StartDate" : "2011-02-16",
"EndDate" : "2012-07-16",
"Amount" : "55067800",
"Subject": [
{
"subjectname": "Sets and Probability",
"score": "78"
},
{
"subjectname": "Networking and Security",
"score": "76"
},
{
"subjectname": "Advanced DataBases",
"score": "72"
},
{
"subjectname": "Economics-2",
"score": "70"
}
]
}
so far I am using this type of controllers as mentioned below:
$scope.addRowSubject = function() {
$scope.insertsub = {
//id = $scope.getSubject.length+1;
subjectname : '1',
score : '1'
};
$scope.getSubject.push($scope.insertsub);
};
getSubject is the list of subjects which are present in one semester field. I am able to get this list without any issues.
$scope.addRowSemester = function() {
$scope.insertsem = {
//id = $scope.getSemester.length+1;
StartDate : "1",
EndDate : "1",
Amount : "1",
SemesterName : "1",
TotalScore : "1",
Subject : ""
}
$scope.getSemester.push($scope.insertsem);
};
getSemester is the list of Semesters in a Student.
I am able to push a semester field inside my JSON but as the Subject field is null i am not able to push the subject field. I hope you are getting the idea.
So any suggestions about this..
Thanks in advance.
Subject properties of your jsonObject is should be an instance of array, like this:
$scope.addRowSemester = function() {
$scope.insertsem = {
//id = $scope.getSemester.length+1;
StartDate : "1",
EndDate : "1",
Amount : "1",
SemesterName : "1",
TotalScore : "1",
Subject : []
}

Javascript - Finding in subarray by value from another array

I have two javascript objects:
var classroom = {
"number" : "1",
"student" : [
{
"number" : 1,
"items" : [
{
"key" : "00000000000000000000001C",
"date" : "2016-04-21T17:35:39.997Z"
}
]
},
{
"number" : 2,
"items" : [
{
"key" : "00000000000000000000001D",
"date" :"2016-04-21T17:35:39.812Z"
},
{
"key" : "00000000000000000000002N",
"date" :"2016-04-21T17:35:40.159Z"
},
{
"key" : "00000000000000000000002Ñ",
"date" :"2016-04-21T17:35:42.619Z"
}
]
}
],
}
AND
var items = [
{
"fields" : {
"tags" : [
{
"key" : "00000000000000000000001C",
"Batch" : "50",
"Bin" : "01",
"Tray" : "02"
},
{
"key" : "00000000000000000000002N",
"Batch" : "55",
"Bin" : "05",
"Tray" : "12"
},
{
"key" : "000000000000228510000032",
"Batch" : "12",
"Bin" : "12",
"Tray" : "01"
}
],
"Name" : "Rubber"
},
"_id" : "56d19b48faa37118109977c0"
},
{
"fields" : {
"tags" : [
{
"key" : "00000000000000000000001D",
"Batch" : "50",
"Bin" : "01",
"Tray" : "05"
},
{
"key" : "00000000000000000000002Ñ",
"Batch" : "52",
"Bin" : "07",
"Tray" : "02"
},
{
"key" : "221567010000000000000089",
"Batch" : "11",
"Bin" : "15",
"Tray" : "03"
}
],
"Name" : "Book"
},
"_id" : "56d19b48faa37118109977c1"
}
];
Ok, I need to create a function that goes through every item of every student in classroom variable. With each item, I need to find in the items array the object that has the exact same key in one of its tags.
My code is getting strange results...missmatching items...
var finalitems = [];
classroom.student.forEach( function (student){
student.items.forEach( function (obj){
items.forEach( function (theitem){
theitem.fields.tags.forEach( function (tag){
if (tag.key === obj.key) {
var newitem = theitem;
newitem.tag = obj;
finalitems.push(newitem);
}
});
});
});
});
I know that foreach is a kind of a pointer but I don't really understand why it is working strange and how it should be done.
Regards,
javascript variables only save object references, not the actual object in memory, so this line:
var newitem = theitem;
means newitem refers to the same object as theitem, NOT create a new object from theitem.
so
newitem.tag = obj;
is the same as
theitem.tag = obj;
Which means you're modifying the input objects, that's why you won't get the expected output.
To get the desired behavior you need to create a copy of theitem and assign that object to newitem variable:
var newitem = Object.create(theitem);
Maybe this helps with a lot more iterations.
var classroom = { "number": "1", "student": [{ "number": 1, "items": [{ "key": "00000000000000000000001C", "date": "2016-04-21T17:35:39.997Z" }] }, { "number": 2, "items": [{ "key": "00000000000000000000001D", "date": "2016-04-21T17:35:39.812Z" }, { "key": "00000000000000000000002N", "date": "2016-04-21T17:35:40.159Z" }, { "key": "00000000000000000000002Ñ", "date": "2016-04-21T17:35:42.619Z" }] }] },
items = [{ "fields": { "tags": [{ "key": "00000000000000000000001C", "Batch": "50", "Bin": "01", "Tray": "02" }, { "key": "00000000000000000000002N", "Batch": "55", "Bin": "05", "Tray": "12" }, { "key": "000000000000228510000032", "Batch": "12", "Bin": "12", "Tray": "01" }], "Name": "Rubber" }, "_id": "56d19b48faa37118109977c0" }, { "fields": { "tags": [{ "key": "00000000000000000000001D", "Batch": "50", "Bin": "01", "Tray": "05" }, { "key": "00000000000000000000002Ñ", "Batch": "52", "Bin": "07", "Tray": "02" }, { "key": "221567010000000000000089", "Batch": "11", "Bin": "15", "Tray": "03" }], "Name": "Book" }, "_id": "56d19b48faa37118109977c1" }],
finalitems = [];
classroom.student.forEach(function (student) {
student.items.forEach(function (studentItem) {
items.forEach(function (item) {
item.fields.tags.forEach(function (itemTag) {
if (itemTag.key === studentItem.key) {
finalitems.push({
key: studentItem.key,
date: studentItem.date,
Batch: itemTag.Batch,
Bin: itemTag.Bin,
Tray: itemTag.Tray,
});
}
});
});
});
});
document.write('<pre>' + JSON.stringify(finalitems, 0, 4) + '</pre>');

Categories