React state and JSON and arrays => faulty result - json

Edit: So, I found the solution to my initial question, which made me realize I have another issue.
It seemed to be easier than I thought
setNumbers(e) {
e.preventDefault();
var already_exists = false;
var ls_data = this.state.storedNumbers;
var rname = document.getElementById('name').value;
var rnumb = document.getElementById('nummer').value;
var ls_key = this.state.ls_key;
for (key in ls_data) {
if(ls_data.hasOwnProperty(key) === true) {
if(ls_data[key].name === rname) {
if(ls_data[key].Number === rnumb) {
already_exists = true;
}
}
}
}
if(!already_exists) {
ls_key++;
ls_data[ls_key] = {
name: rname,
Number: rnumb
};
localStorage.setItem("ls_numbers", JSON.stringify(this.state.storedNumbers));
localStorage.setItem("ls_key", ls_key);
this.setState({
ls_key: localStorage.getItem("ls_key"),
});
}
}
But now my issue is, that I can't iterate over it, because it is a nested object and not an array. So .map will not work (this.state.storedNumbers.map is not a function).
Changing storedNumber to an array sadly doesn't solve the issue, as
ls_data[ls_key] = {
name: rname,
Number: rnumb
};
isn't working in an array. So now my question is. Can I use my ls_key variable to create a name object in my array? Using the code above results in:
[
null,
{
"name" : "Person 1",
"Number" : "XXXXXXXX"
},
{
"name" : "Person 2",
"Number" : "XXXXXXXX"
}
]
while the array should look like:
[
"1": {
"name" : "Person 1",
"Number" : "XXXXXXXX"
},
"2": {
"name" : "Person 2",
"Number" : "XXXXXXXX"
}
]
Or is there a way to iterate over the nested JSON result, as .map does for an array?

Alright then, just figured it out myself:
The reason my data got malformed (initial question), still in the blue about that. I've changed a lot of code and reverted to the original code again, et voila, miraculously it all worked. Can't tell you what the difference was. After that I could easily simplify the code as shown in the edited question.
To iterate over the data, the code below was my solution. Should you have a more cleaner solution, let me know!
{this.state.storedNumbers.length < 1
? <li className='list-group-item'><strong>Geen recente nummers...</strong><span className='pull-right'><span className='glyphicon glyphicon-warning glyph-xl'></span></span></li>
: Object.keys(this.state.storedNumbers).map((number) => {
return (
<div className='item' key={number}>
<a className='list-group-item list-link'>
<strong>{this.state.storedNumbers[number].name}</strong> - ({this.state.storedNumbers[number].Number})
</a>
<span className='button-delete glyph-xl'>
<i className='glyphicon glyphicon-trash glyph-xl' aria-hidden='true'></i>
</span>
</div>
)})
}

Related

Unable to parse JSON data due to errors or undefined data

I apologize if this seems similar to other questions asked but I have not been able to find any posts that have resolved this issue for me. Basically, I am getting a JSON object and I am trying to parse it but I can't parse it correctly. Mainly the WordDetails section that I am getting from a Word API. I am able to get everything outside the results section under WordDetails. Basically, when I get to results, I am not able to parse it correctly. Below is an example of the format.
{
"LastIndex": 133,
"SRDWords": [
{
"Domain": {
"URL": "abactinal.com",
"Available": true
},
"WordDetails": "{\"word\":\"abactinal\",\"results\":[{\"definition\":\"(of radiate animals) located on the surface or end opposite to that on which the mouth is situated\",\"partOfSpeech\":null,\"antonyms\":[\"actinal\"]}],\"syllables\":{\"count\":4,\"list\":[\"ab\",\"ac\",\"ti\",\"nal\"]}}"
},
{
"Domain": {
"URL": "aaronical.com",
"Available": true
},
"WordDetails": "{\"word\":\"aaronical\",\"syllables\":{\"count\":4,\"list\":[\"aa\",\"ron\",\"i\",\"cal\"]},\"pronunciation\":{\"all\":\"ɜ'rɑnɪkəl\"}}"
},
...
Here is my code below. Basically, I am getting to the results section of WordDetails but if I try to parse the results section it fails and if I try object.entries on it, it will not return a response according to the alert messages I used. I know there must be a better way but not sure what. Most articles say just JSON.parse then map it but that does not work. Any help would be appreciated!
data.Words.map(word => {
//get data
for (let [key, value] of Object.entries(word)) {
if (key === "Domain") {
url = value.URL;
availability = value.Available;
} else if (key.trim() === "WordDetails") {
alert("value " + value);
wDetails = JSON.parse(value);
for (let [key2, value2] of Object.entries(wDetails)) {
if (key2 === "word") {
//store word
} else if (key2.toString().trim() === "results") {
let test = JSON.parse(value2);
test = Object.entries(value2);
test.map(t => {
alert(t.definition);
});
}
}
}
}
});
You did JSON.parse above, no need to parse value2 again.
And value for results is an array, so no need for Object.entries.
...
} else if (key2.toString().trim() === 'results') {
let test = JSON.parse(value2); // this should be remove
test = Object.entries(value2); // this should be remove, value2 should be an array
// map value2 directly
value2.map(t => {
alert(t.definition);
});
}
...

Restructuring JSON Response in Angular 2+

I'm currently receiving a web api JSON response that is heavily nested and I want to restructure it plucking out only the data I need and making it more simple.
How would I do this in Angular 2+/Typescript?
Any help would be really appreciated.
Say I have something like this:
"O1": {
"P1": "Something",
"A1": [{
"P2": "Something",
"A2": [{
"P3": "Something"
}]
}]
"P4": "Something"
}
and I want to restructure it to this :
"O1": {
"P1": "Something",
"P2": "Something",
"P3": "Something"
}
Can I rebuild the model in a class in the constructor? If so, I haven't been able to find anything online as of yet.
Let me know if I need to provide any further info.
Thanks
Let's flatten the initial object using the snippet which was proposed. And then we can filter those properties which we need to include in the final object:
function filterObj(obj: any, propsForFilter: string[]) {
const result = {};
for (let prop in obj) {
const filteredProp = propsForFilter.find(p => prop.includes(p));
if (filteredProp) {
result[filteredProp] = obj[prop];
}
}
return result;
}
const flattened = flattenObject(obj);
console.log(flattened, filterObj(flattened, ['P1', 'P2']));
This method filterObj accepts the array of properties in order to include them in the final result. Hope this will be helpful for you.
Found this snippet in github:
https://gist.github.com/penguinboy/762197
var flattenObject = function(ob) {
var toReturn = {};
for (var i in ob) {
if (!ob.hasOwnProperty(i)) continue;
if ((typeof ob[i]) == 'object') {
var flatObject = flattenObject(ob[i]);
for (var x in flatObject) {
if (!flatObject.hasOwnProperty(x)) continue;
toReturn[i + '.' + x] = flatObject[x];
}
} else {
toReturn[i] = ob[i];
}
}
return toReturn;
}

How to convert a MongoDB document to JSON Object

I am trying to make a post request with the MongoDB document returned from find query, as the request body in NodeJS.But on the server I'm getting the Error : Invalid JSON. Below is the document that I'm trying to POST
{
"_id" : ObjectId("5739a6bf3f1b41477570dc89"),
"taskCount" : 2,
"study" : "cod",
"phase" : "mansa2",
"rhimeTaskId" : "5739a6bec4567f6e737fd3db",
"recordId" : "5726f3cfc4567f6e737fc3ab",
"recordStudy" : "codstudy",
"recordPhase" : "mansa2",
"recordLanguage" : "Punjabi",
"recordScript" : "Latin",
"_state" : "CodingComplete",
"tasks" : [
{
"physician" : ObjectId("5739a6bd3f1b41477570dc78"),
"stage" : "Coding",
"result" : {
"cod" : "C15",
"feedback" : {
"narrativeLength" : "Adequate",
"positiveSymptomsIncluded" : "Only Positive",
"certainty" : "High"
},
"keywords" : [
"52 yr male, died of food pipe cancer, suffered pain upper abdomen, investigated,FNAC confirmed Cancer, Put on Chemotherapy, multiple cycles, died at home, had fever with chills occasionally"
]
}
},
{
"physician" : ObjectId("5739a6bd3f1b41477570dc79"),
"stage" : "Coding",
"result" : {
"cod" : "C15",
"feedback" : {
"narrativeLength" : "Inadequate",
"positiveSymptomsIncluded" : "Only Positive",
"certainty" : "High"
},
"keywords" : [
"severe pain abdomen, ultrasonography revealed food pipe cancer, chemotherapy given, died"
]
}
}
],
"__v" : 2
}
and here is the code that I wrote to make the POST request
var MongoClient = require('mongodb').MongoClient;
var request = require('request');
var assert = require('assert');
var cmeprovisioning= 'mongodb://localhost:27017/cmeprovisioning';
MongoClient.connect(cmeprovisioning, function(err, db) {
assert.equal(null, err);
var count=0;
console.log("Connected to cmeprovisioning");
var cursor =db.collection('rhimeReport').find(
{"study":"cod","phase":"mansa2","recordStudy":"codstudy",
"recordPhase":"mansa2","_state":"CodingComplete"
});
cursor.each(function(err, doc) {
assert.equal(err, null);
if (doc != null) {
console.dir(doc);
count=count+1;
request({url: "http://cme.host.net:8081/cme-provisioning/update",
method: "POST",json: true,
headers: {"content-type": "application/json"},
json: doc
},function(e,r,b){
console.log("POST Error "+count+" "+e)
console.log("POST Response "+count+" "+r)
console.log("POST BODY "+count+" "+b)
});
} else {
console.log("Some Error : "+err)
}
});
});
I also tried using JSON.stringify(doc), but still got the Invalid JSON error. Is there a way I can use mongo document returned by the find query and convert it to JSON to make the POST request.
I think those ObjectID is what making it an invalid JSON document.
Here's the actual answer:
If you want to convert a mongo object to JSON object.
There's a utility method in every mongo object toJSON
So you can simply do mongoResponseObject.toJSON() on the response object.
e.g.
Products.findById(id).then(res => {
const jsonRes = res.toJSON();
// Here jsonRes is JSON
})
Alternatively you can directly get the JSON object by using the .lean() like this.
Products.findById(id).lean().then(res => {
// Here res is JSON
})
you need to convert object id to string ie.
var result = {
"_id": ObjectId("5739a6bf3f1b41477570dc89"),
"taskCount": 2,
"study": "cod"
};
//now convert to string
result=result._id.toString();
//now you can use the result
Try this,
var cursor =db.collection('rhimeReport').find(
{"study":"cod","phase":"mansa2","recordStudy":"codstudy",
"recordPhase":"mansa2","_state":"CodingComplete"});
cursor.toString();
......
Hope this help.
Try this in robomongo
var cursor = db.getCollection('X').find({},{})
while(cursor.hasNext()) {
print(JSON.stringify(cursor.next()))
}

How to get only part of the document while querying with mongoose?

I have following
{
"_id" : ObjectId("56d808d826941f84bc697b4e"),
"outerArray" : [
{
"middleArray" : [
{
"someKey": "value",
"innerArray" : [
"F999-99999",
"F999-999999",
"FAF-99999",
"FSF-99999",
"FSW-99999",
"FSX-99999",
"FAF-999999",
"FSF-999999",
"FSW-999999",
"FSX-999999"
]
}
]
}
]
}
when I query
Model.find({outerArray.middleArray.someKey = 'value'},outerArray.middleArray.innerArray)},function(err,results){
//do some thing
}
I am getting innerArray along with the outer structure. But what i want is only innerArray part like -
"innerArray" : [
"F999-99999",
"F999-999999",
"FAF-99999",
"FSF-99999",
"FSW-99999",
"FSX-99999",
"FAF-999999",
"FSF-999999",
"FSW-999999",
"FSX-999999"
]
so i dont need to traverse through all outer arrays like outerArray[0].middleArray[0].innerArray
I looked into projections but i am not able to find anything. Please help me with this. Thanks a Lot ...
how about this?
var _ = require('lodash');
var data = {
"_id" : "SOMETHING",
"outerArray" : [
{
"middleArray" : [
{
"someKey": "value",
"innerArray" : [
"F999-99999",
"F999-999999",
"FAF-99999",
"FSF-99999",
"FSW-99999",
"FSX-99999",
"FAF-999999",
"FSF-999999",
"FSW-999999",
"FSX-999999"
]
}
]
}
]
}
data = _.result(data, "outerArray[0].middleArray[0].innerArray", null);
console.log(data);
Also have You tried this ?
Model.find(
{outerArray.middleArray.someKey: 'value'},
'outerArray.middleArray.innerArray',
function(err,results){
console.log(results);
});
You can't do what you want, directly.
MongoDB is a document database, not a relational database. When you retrieve (find) a document, it will retrieve the entire document, always.
If you only want the inner array, you need to pull that out of the full document that was returned to you.

Searching in JSON for specific value using AngularJS

I am trying to filter my JSON object by a specific property value set to Log: true
If an object has this property set to false, I want to filter it out. Here is an example of the JSON structure:
$scope.Main =
{
"MyBook" :
{
"Title": "The Road",
"Type" : "Text",
"Log" : false
},
"MyCat":
{
"Name" : "Penny",
"Type" : "Pet",
"Log" : true
},
"Car":
{
"Make" : "Toyota",
"Model" : "Camry",
"Type" : "Vehicle",
"Log" : false
}
}
As you can see, the objects themselves are not similar, but they all contains a log property.
Online Demo
This is how I would filtered an object while searching for a property value equals true
var sampleObj = {/* you sample object*/};
var filtered = Object.keys(sampleObj).reduce(function(arr,prop){
if(Object.keys(sampleObj[prop])
.filter(function (p) {return p === "Log";})){
if(sampleObj[prop].Log==true){
arr.push(sampleObj[prop]);
}
}
return arr;
},[]);
console.log(filtered);
Since you are using angular probably you would want to use a custom filter instead:
Something close to:
custom filter:
angular.module('myApp', []).filter('myFilter', function() {
return function(sampleObj, param1) {
return Object.keys(sampleObj).reduce(function(arr,prop){
if(Object.keys(sampleObj[prop])
.filter(function (p) {return p === "Log";})){
if(sampleObj[prop].Log==param1){
arr.push(sampleObj[prop]);
}
}
return arr;
},[]);
};
});
and in your html
<li ng-repeat="item in sampleObj | myFilter: true">
try using the underscorejs library.
you can use some of their functions like _.filter and _.has to filter the list.
here's an example of how i would try to implement that object:
var filtered = _.filter($scope.Main, function(obj) {
return _.has(obj, "Log") && obj.Log;
}
Use a custom Angular filter:
.filter('filterLog', function(){
return function(items){
for (var item in items) {
if (items[item].Log === false) delete items[item];
}
return items;
}
})
Then, in your view, you could output the filtered list like so:
<li ng-repeat="(key, value) in Main | filterLog">{{value}}</li>
If you need to use it in a controller, you could:
$scope.filtered = $filter('filterLog')($scope.Main);
Demo