Complex JSON nesting of objects and arrays - javascript

I am having difficultly with syntax and structure of JSON objects/arrays.
{
"accounting" : [
{ "firstName" : "John",
"lastName" : "Doe",
"age" : 23 },
{ "firstName" : "Mary",
"lastName" : "Smith",
"age" : 32 }
],
"sales" : [
{ "firstName" : "Sally",
"lastName" : "Green",
"age" : 27 },
{ "firstName" : "Jim",
"lastName" : "Galley",
"age" : 41 }
]
}
I want to make a nested structure of objects and arrays that would house the following info:
{
"problems": [{
"Diabetes":[{
"medications":[{
"medicationsClasses":[{
"className":[{
"associatedDrug":[{
"name":"asprin",
"dose":"",
"strength":"500 mg"
}],
"associatedDrug#2":[{
"name":"somethingElse",
"dose":"",
"strength":"500 mg"
}]
}],
"className2":[{
"associatedDrug":[{
"name":"asprin",
"dose":"",
"strength":"500 mg"
}],
"associatedDrug#2":[{
"name":"somethingElse",
"dose":"",
"strength":"500 mg"
}]
}]
}]
}],
"labs":[{
"missing_field": "missing_value"
}]
}],
"Asthma":[{}]
}]}
But I have no idea what the right way to do this should be. Should I just be making JavaScript objects? Does JSON make sense for this project?
What is the correct syntax to set something like this up?
Here is my code so far:
$(document).ready(function() {
$.getJSON('js/orders.json', function(json) {
$.each(json.problems, function(index, order) {
$('.loadMeds').append('<p>' + order.name + '</p>')
});
});
});

The first code is an example of Javascript code, which is similar, however not JSON. JSON would not have 1) comments and 2) the var keyword
You don't have any comments in your JSON, but you should remove the var and start like this:
orders: {
The [{}] notation means "object in an array" and is not what you need everywhere. It is not an error, but it's too complicated for some purposes. AssociatedDrug should work well as an object:
"associatedDrug": {
"name":"asprin",
"dose":"",
"strength":"500 mg"
}
Also, the empty object labs should be filled with something.
Other than that, your code is okay. You can either paste it into javascript, or use the JSON.parse() method, or any other parsing method (please don't use eval)
Update 2 answered:
obj.problems[0].Diabetes[0].medications[0].medicationsClasses[0].className[0].associatedDrug[0].name
returns 'aspirin'. It is however better suited for foreaches everywhere

I successfully solved my problem. Here is my code:
The complex JSON object:
{
"medications":[{
"aceInhibitors":[{
"name":"lisinopril",
"strength":"10 mg Tab",
"dose":"1 tab",
"route":"PO",
"sig":"daily",
"pillCount":"#90",
"refills":"Refill 3"
}],
"antianginal":[{
"name":"nitroglycerin",
"strength":"0.4 mg Sublingual Tab",
"dose":"1 tab",
"route":"SL",
"sig":"q15min PRN",
"pillCount":"#30",
"refills":"Refill 1"
}],
"anticoagulants":[{
"name":"warfarin sodium",
"strength":"3 mg Tab",
"dose":"1 tab",
"route":"PO",
"sig":"daily",
"pillCount":"#90",
"refills":"Refill 3"
}],
"betaBlocker":[{
"name":"metoprolol tartrate",
"strength":"25 mg Tab",
"dose":"1 tab",
"route":"PO",
"sig":"daily",
"pillCount":"#90",
"refills":"Refill 3"
}],
"diuretic":[{
"name":"furosemide",
"strength":"40 mg Tab",
"dose":"1 tab",
"route":"PO",
"sig":"daily",
"pillCount":"#90",
"refills":"Refill 3"
}],
"mineral":[{
"name":"potassium chloride ER",
"strength":"10 mEq Tab",
"dose":"1 tab",
"route":"PO",
"sig":"daily",
"pillCount":"#90",
"refills":"Refill 3"
}]
}
],
"labs":[{
"name":"Arterial Blood Gas",
"time":"Today",
"location":"Main Hospital Lab"
},
{
"name":"BMP",
"time":"Today",
"location":"Primary Care Clinic"
},
{
"name":"BNP",
"time":"3 Weeks",
"location":"Primary Care Clinic"
},
{
"name":"BUN",
"time":"1 Year",
"location":"Primary Care Clinic"
},
{
"name":"Cardiac Enzymes",
"time":"Today",
"location":"Primary Care Clinic"
},
{
"name":"CBC",
"time":"1 Year",
"location":"Primary Care Clinic"
},
{
"name":"Creatinine",
"time":"1 Year",
"location":"Main Hospital Lab"
},
{
"name":"Electrolyte Panel",
"time":"1 Year",
"location":"Primary Care Clinic"
},
{
"name":"Glucose",
"time":"1 Year",
"location":"Main Hospital Lab"
},
{
"name":"PT/INR",
"time":"3 Weeks",
"location":"Primary Care Clinic"
},
{
"name":"PTT",
"time":"3 Weeks",
"location":"Coumadin Clinic"
},
{
"name":"TSH",
"time":"1 Year",
"location":"Primary Care Clinic"
}
],
"imaging":[{
"name":"Chest X-Ray",
"time":"Today",
"location":"Main Hospital Radiology"
},
{
"name":"Chest X-Ray",
"time":"Today",
"location":"Main Hospital Radiology"
},
{
"name":"Chest X-Ray",
"time":"Today",
"location":"Main Hospital Radiology"
}
]
}
The jQuery code to grab the data and display it on my webpage:
$(document).ready(function() {
var items = [];
$.getJSON('labOrders.json', function(json) {
$.each(json.medications, function(index, orders) {
$.each(this, function() {
$.each(this, function() {
items.push('<div class="row">'+this.name+"\t"+this.strength+"\t"+this.dose+"\t"+this.route+"\t"+this.sig+"\t"+this.pillCount+"\t"+this.refills+'</div>'+"\n");
});
});
});
$('<div>', {
"class":'loaded',
html:items.join('')
}).appendTo("body");
});
});

Make sure you follow the language definition for JSON. In your second example, the section:
"labs":[{
""
}]
Is invalid since an object must be composed of zero or more key-value pairs "a" : "b", where "b" may be any valid value. Some parsers may automatically interpret { "" } to be { "" : null }, but this is not a clearly defined case.
Also, you are using a nested array of objects [{}] quite a bit. I would only do this if:
There is no good "identifier" string for each object in the array.
There is some clear reason for having an array over a key-value for that entry.

First, choosing a data structure(xml,json,yaml) usually includes only a readability/size problem. For example
Json is very compact, but no human being can read it easily, very hard do debug,
Xml is very large, but everyone can easily read/debug it,
Yaml is in between Xml and json.
But if you want to work with Javascript heavily and/or your software makes a lot of data transfer between browser-server, you should use Json, because it is pure javascript and very compact. But don't try to write it in a string, use libraries to generate the code you needed from an object.
Hope this helps.

You can try use this function to find any object in nested nested array of arrays of kings.
Example
function findTByKeyValue (element, target){
var found = true;
for(var key in target) {
if (!element.hasOwnProperty(key) || element[key] !== target[key]) {
found = false;
break;
}
}
if(found) {
return element;
}
if(typeof(element) !== "object") {
return false;
}
for(var index in element) {
var result = findTByKeyValue(element[index],target);
if(result) {
return result;
}
}
};
findTByKeyValue(problems,{"name":"somethingElse","strength":"500 mg"}) =====> result equal to object associatedDrug#2

Related

Sequelize find based on association and nested [Op.and]

I'm writing here because I'm completely lost. I would like to do a findall based on association and nested [Op.and], but I can't do it. Let me explain.
I have two tables (car and properties) with an association between these two tables (one car, can have several properties). The data looks like this :
{
"car": "BMW M5",
"properties": [
{
"name": "make",
"value": "bmw"
},
{
"name": "color",
"value": "blue"
}
]
},
{
"car": "AUDI A3",
"properties": [
{
"name": "make",
"value": "audi"
},
{
"name": "color",
"value": "black"
}
]
},
What I'm trying to do is a "findAll" of all cars of make BMW and with blue color. Logically, I would see something like this :
( properties.name = make & properties.value = audi ) & ( properties.name = color & properties.value = blue )
From this logic, I therefore tried to create the sequelize command below, but without success :
const cars = await models.Car.findAll({
include: [{
model: models.Properties,
required: false,
}],
where: {
[Sequelize.Op.and]:[
{[Sequelize.Op.and]: [{"$properties.name$": "make"}, {"$properties.value$": "bmw"}]},
{[Sequelize.Op.and]: [{"$properties.name$": "color"}, {"$properties.value$": "blue"}]},
]
});
Apparently when I do this it only takes the last [Op.and] ([Sequelize.Op.and]: [{"$properties.name$": "color"}, {"$properties.value$": "blue"}]), the others don't seem to be taken into consideration.
Maybe I'm wrong, but I tried several possibilities, but I don't know how to do it. Any help would be very appreciated, thank you in advance to everyone.
It seems you over-complicated the where condition:
const cars = await models.Car.findAll({
include: [{
model: models.Properties,
required: false,
}],
where: {
[Sequelize.Op.and]:[
{
"$properties.name$": "make",
"$properties.value$": "bmw"
},
{
"$properties.name$": "color",
"$properties.value$": "blue"
},
]
}
});
If you have different props in the same group of conditions then you can just use an object to combine them with AND operator.

Loop through array of objects and check conditions

I have an array of object like this
list = [
{
"label" : "whatever",
"value" : "value 1"
},
{
"label" : "whatever",
"value" : "value 2"
},
{
"label" : "Required scenario only",
"value" : "value 3"
},
{
"label" : "whatever",
"value" : "value 4"
},
]
I am running for a loop with conditions, I want to execute some piece of code only for one scenario called 'Required scenario only' for the rest of all scenarios run different code for only one time, it should not execute 3 times as per loop executes
for(i=0; i< list.length; i++) {
if(list[i].label === 'Required scenario only' ) {
//execute some code
} else {
// execute code for 1 time for rest of the labels i.e for all 'whatever' scenarios
}
}
How should I do it?
If you're merely checking for the existence of an object with label = "Required scenario only" then I would use Array.some():
list = [{
label: "whatever",
value: "value 1"
},
{
label: "whatever",
value: "value 2"
},
{
label: "Required scenario only",
value: "value 3"
},
{
label: "whatever",
value: "value 2"
},
]
if (list.some(l => (l.label == "Required scenario only"))) {doSomething();}
else {doSomethingElse();}
function doSomething() {console.log("Do Something");}
function doSomethingElse() {console.log("Do Something Else");}

Elastic-search: How can i map json data having dynamic number of fields

I'm working on a application for that i need to map json data for storing in Elasticsearch. The number of fields in json data is dynamic.then how can i do mapping for this scenario.
mapping Snippet
var fs = uploadedFiles[0].fd;
var xlsxRows = require('xlsx-rows');
var rows = xlsxRows(fs);
console.log(rows);
client.indices.putMapping({
"index": "testindex",
"type": "testtype",
"body": {
"testtype": {
"properties": {
"Field 1": {
"type": "string"
},
"Field 3": {
"type": "string"
},
"Field 2":{
"type":"string"
} .....
//Don't know how many fields are in json object.
}
}
}
}, function (err, response) {
if(err){
console.log("error");
}
console.log("REAPONCE")
console.log(response);
});
This is my sample json data
//result of rows
[
{ Name: 'paranthn', Age: '43', Address: 'trichy' },
{ Name: 'Arthick', Age: '23', Address: 'trichy' },
{ Name: 'vel', Age: '24', Address: 'trichy' } //property fields
]
NOTE: The number of property fields are dynamic.
ES will always make its best efforts to infer the correct type for the fields in your documents that have no mapping defined and set sensible defaults.
A mapping is only necessary if you need to apply some special treatment to certain fields other than the set defaults, like specifying an indexing analyzer, a search analyzer, whether string fields need to be analyzed or not, specifying sub-fields with a different analyzer, etc.
If you don't need any of this, then you can let ES infer the mapping of your documents.

Using typeahead.js with Json

I'm following this link which is a great clear blog post about typeahead.js with Json. However, I'm having problems with it and can't figure out where I'm going wrong.
Here is my js:
<script type="text/javascript">
$('#Search').typeahead({
hint: true,
highlight: true,
minLength: 1
},
{
name: 'states',
displayKey: 'stateName',
source: function (query, process) {
states = [];
map = {};
var data = [
{ "stateCode": "CA", "stateName": "California" },
{ "stateCode": "AZ", "stateName": "Arizona" },
{ "stateCode": "NY", "stateName": "New York" },
{ "stateCode": "NV", "stateName": "Nevada" },
{ "stateCode": "OH", "stateName": "Ohio" }
];
$.each(data, function (i, state) {
map[state.stateName] = state;
states.push(state.stateName);
});
process(states);
},
updater: function (item) {
selectedState = map[item].stateCode;
return item;
}
});
</script>
When I type in the input control all the results come back as undefined. I think it's something to do with the displayKey and I've tried setting it to state.stateName but that results in the same problem. Maybe I'm looking in the wrong area?
I've setup a plnkr.co demo here.
Thanks for reading.
Paul
You need to change your states.push row, in your plunker it is on row 45.
Typeahead expects results in JSON format, now you are just pushing results.
Change row 45 to:
states.push({stateName : state.stateName});
Now your displayKey: "stateName" (which is the key of JSON formatted data) will exist and it will show the name of the state as a result.

angularjs - select with object of object as options

I'm currently trying to build a AngularJS app with a complex data structure.
The data source is an array of people with languages and skill level.
I need to filter those people by language skill, to do so I tried to build a select with the languages and another select with the skill levels, but i failed.
Here is a plnkr of my effords
Maybe there is also a simpler/better way to structure the data array ($scope.people)
Take a look at this
Working Demo
Html
<div ng-app='myApp' ng-controller="MainCtrl">LANGUAGES:
<select ng-model="selectLang" ng-options="lang as lang for lang in languages"></select>
<br>SKILL:
<select ng-model="selectSkill" ng-options="skill as skill for skill in skills"></select>
<br>
<button ng-click="getPeople()">Submit</button>
<br>PEOPLE:
<select ng-model="selectPeoples" ng-options="people as people for people in peoples"></select>
</div>
script
var app = angular.module('myApp', []);
app.controller('MainCtrl', function ($scope) {
$scope.people = [{
"name": "Jane Doe",
"gender": "Female",
"languages": [{
"lang": "German",
"skill": "Good"
}, {
"lang": "English",
"skill": "Very Good"
}]
}, {
"name": "John Doe",
"gender": "Male",
"languages": [{
"lang": "French",
"skill": "Good"
}, {
"lang": "English",
"skill": "Very Good"
}]
}];
$scope.languages = [];
$scope.skills = [];
angular.forEach($scope.people, function (peopleValue, peopleKey) {
angular.forEach(peopleValue.languages, function (langValue, langKey) {
$scope.languages.push(langValue.lang);
$scope.skills.push(langValue.skill);
});
});
$scope.languages = _.uniq($scope.languages);
$scope.skills = _.uniq($scope.skills);
$scope.getPeople = function () {
$scope.peoples = [];
angular.forEach($scope.people, function (peopleValue, peopleKey) {
angular.forEach(peopleValue.languages, function (langValue, langKey) {
if (langValue.lang === $scope.selectLang && langValue.skill === $scope.selectSkill) {
$scope.peoples.push(peopleValue.name);
}
});
});
}
});
Your problem is that you're not actually looping through each person's languages array in your ng-options directive. And I don't believe such a thing is actually possible given how your data is structured. I don't think you can loop through nested arrays (or at least I'm not aware of any ng-options syntax that would allow for such a thing.
So to make things easier, I would suggest doing the following in your controller:
$scope.langs = [];
angular.forEach($scope.people, function(person){
angular.forEach(person.languages, function(lang){
$scope.langs.push({
lang: lang.lang,
skill: lang.skill,
name: person.name,
gender: person.gender
});
});
});
This will give you an array that will allow you to filter using ng-options with the `orderBy' filter.

Categories