I lose the reference of the "value" variable when it is no longer in the "onsuccess" context. I don't know how to make this function asymmetric.
getList(){
let transaction = this.db.transaction([this.db_name], "readwrite");
transaction.oncomplete= _ => {
console.log("Success")
}
transaction.onerror = _ => {
console.log("Error")
}
let value = []
let objectStore = transaction.objectStore(this.db_name)
objectStore.getAll().onsuccess = e => {
value = e.target.result;
};
console.log(value)
return value
}
When I console.log(value) I get an empty array.
If I wanted to take this data and put it directly in my HTML it would have worked and these are the only examples I managed to find on the internet
Trying to parse and read my JSON data.
I am passing my json data from Xcode to my React native front-end.
I have tried JSON.parse and JSON.stringify nothing works.
It always logs "NULL". I need to access the "value"
Help please!!
JSON in Xcode
{
"myDictionary" : {
"BG" : [
"{\"value\":\"8 mg\\\/dL\",\"endDate\":635390040,\"startDate\":635390040,\"type\":\"bloodGlucose\"}",
"{\"value\":\"6 mg\\\/dL\",\"endDate\":635393640,\"startDate\":635393640,\"type\":\"bloodGlucose\"}"
]
}
}
JS:
const log = HealthkitController.getBloodGlucose()
.then(result => {
let res = JSON.parse(result)
for (let i = 0; i < res.length; i++) {
let final = res[0];
console.log(final) // prints the first object
let fin = final["value"]
console.log(fin) //undefined (doesn't print 8mg/dL)
}
})
result:
["{\"value\":\"8 mg\\\/dL\",\"endDate\":635390040,\"startDate\":635390040,\"type\":\"bloodGlucose\"}",
"{\"value\":\"6 mg\\\/dL\",\"endDate\":635393640,\"startDate\":635393640,\"type\":\"bloodGlucose\"}"]
Your result is coming back as an Array of strings. If you want to extract the value you can do something like this
const values = results.map(result => {
const { value } = JSON.parse(result);
return value;
});
The output will be:
["8 mg/dL", "6 mg/dL"]
What does this create?
const log = HealthkitController.getBloodGlucose()
.then(result => {
for (var i = 0; i < result.lenght; i++{
let res = JSON.parse(result[i])
console.log(res) //always null
}
});
I have a code that accepts a list of nested objects, each of which should be converted to a log row.
The code goes through a loop on each object, then an inner loop on each property, and extracts its property (there are hundreds of properties), then puts all the information of a row - as a map of the object's name and its value, into a variable called returnVar.
We use the 'fast-csv' library, with WriteStream that is named csvStream. also with a fs.createWriteStream pipe.
Finally, we loop over each object and write it with csvStream.write(),
that will insert the properties name in the first line of the file, and the logs (in the same order) in the other lines.
I need to change the code so that instead of doing pipe to file stream, it will print to a string type variable.
This is the code:
let Promise = require('bluebird');
let csv = require('fast-csv');
let fs = Promise.promisifyAll(require('fs'));
...
return new Promise(function (resolve, reject) {
var csvStream = csv.createWriteStream({ headers: propNames })
.transform(function (item) { // every item is a nested object that contains data for a log line
var returnVar = {}; // every returnVar will represents a map of property and value, that will be transform to a log line
for (var prop in item) {
if (item.hasOwnProperty(prop)) {
if (propNames.indexOf(prop) >= 0) {
if (typeof item[prop] === 'object') {
returnVar[prop] = JSON.stringify(item[prop]);
}
else {
returnVar[prop] = item[prop];
}
}
//the object might be a complex item that contains some properties that we want to export...
else if (typeof item[prop] === 'object') {
var nestedItem = item[prop];
for (var nestedProp in nestedItem) {
if (propNames.indexOf(prop + "_" + nestedProp) >= 0) {
returnVar[prop + "_" + nestedProp] = nestedItem[nestedProp];
}
}
}
}
}
return returnVar; // return log line
});
// create file path
var fileId = "Report_" + cryptoService.generateRandomPassword(16) + ".csv";
var filePath = tempPath + fileId;
getOrCreateTempDirectory().then(function () {
var writableStream = fs.createWriteStream(filePath);
writableStream.on("finish", function () {
resolve({
fileId: fileId
});
});
csvStream.pipe(writableStream);
_.each(results.records, function (result) {
// write line to file
csvStream.write(result._source);
});
csvStream.end();
});
});
https://c2fo.io/fast-csv/docs/formatting/methods#writetobuffer
https://c2fo.io/fast-csv/docs/formatting/methods#writetostring
Change
csvStream.write(result._source);
to
csvStream.writeToString(result._source).then(data => console.log(data));
Promise.all(_.map(results.records, result => csvStream.writeToString(result._source)))
.then(rows=>console.log(rows))
// rows should be an array of strings representing all the results
You can also use async/await
I have a json like this:
{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"}]}}
... and I dynamically fetch the values and create a variable this:
var existingParams = [
"name",
"updated"].filter(field => getBody.search[field]);
var sqlVal = existingParams.map(field => {
if (field === 'name') {
function getValues(item, index) {
var getVal = [item.tag];
return "%" + getVal + "%";
}
console.log(name.map(getValues));
return name.map(getValues);
} else {
return getBody.search[field];
}
})
For the above example I get for sqlVal:
console.log(sqlVal);
[ [ '%Peter%' ], '2018-11-07' ]
... which is fine.
BUT, if I have two values:
{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"}]}}
... I'm getting this structure:
[ [ '%Peter%', '%Jack%' ], '2018-11-07' ]
... but what I need is sth like:
[ '%Peter%', '%Jack%', '2018-11-07' ]
... or:
[ ['%Peter%'], ['%Jack%'], '2018-11-07' ]
And in case of further e.g. 3 names:
{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"},{"tag":"Maria"}]}}
... I need sth like:
[ '%Peter%', '%Jack%', '%Maria%', '2018-11-07' ]
... or:
[ ['%Peter%'], ['%Jack%'], ['%Maria%'], '2018-11-07' ]
... and so on
How do I need to adjust the above query to get this?
If I understand your question correctly, then this problem can be solved via the Array#reduce() method.
The general idea with this approach is to transform your input object to an array - the reduce operation can be used to do this, with the special-case rule of "flattening" the nested value on the name key into the final result:
var input = {"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"}]}}
var result = Object
.entries(input.search)
.reduce(function(result, entry) {
const key = entry[0]
const value = entry[1]
if(key === 'name') {
// When the 'name' key is encountered, handle the value
// differently, by addting the items of this value array
// to the result
value.forEach(function(item) {
result.push('%' + item.tag + '%')
})
}
else {
// Append values for other keys directly to the result
result.push(value)
}
return result
}, [])
console.log(result )
You could simply use Object.values + reduce for something like this:
const json = { "search": { "updated": "2018-11-07", "name": [{ "tag": "Peter" }, { "tag": "Jack" }, { "tag": "Maria" }] } }
const result = Object.values(json.search).reduce((r,c) =>
(Array.isArray(c) ? r.push(...c.map(({tag}) => `%${tag}%`)) : r.push(c), r),[])
console.log(result)
If the order is important (names first then date) you could use reverse:
const json = { "search": { "updated": "2018-11-07", "name": [{ "tag": "Peter" }, { "tag": "Jack" }, { "tag": "Maria" }] } }
const result = Object.values(json.search).reverse().reduce((r,c) =>
(Array.isArray(c) ? r.push(...c.map(({tag}) => `%${tag}%`)) : r.push(c), r),[])
console.log(result)
First of all you did not provide a Minimal, Complete, and Verifiable example so it is quite hard for me to figure out where you are running into issues. For example, you are referencing existingParam but nowhere are they defined. This is key to understanding the problem because all of the code that you posted is heavily invested in the values and format of this value.
Second, how are you parsing the JSON? With the standard JSON#parse function you would get back an object with the same structure as your provided JSON. However, you are either not using this or you are mutating the object after it was parsed into a new format. Either way, the object that JSON#parse returns for the provided JSON is not an array and therefor you cannot use Array#map on it.
For the sake of being productive though I am going to try and explain how to do things.
JSON:
let data1 = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"}]}}',
data2 = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"}]}} ',
data3 = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"},{"tag":"Maria"}]}}';
Now that we have our JSON data we need to parse it and store it as a JSON object. To do so I am going to create a function; this way the data can be passed to the same function and handled the same way but the implementation will stay the same. Also, since we are only looking at the values in the search property we are going to go ahead and jump right into it.
Parse the JSON:
function parseResponse (response) {
let parsedResponse = JSON.parse(response);
parsedResponse = parsedResponse['search'];
}
Now that we have our function that takes our response and parses it we can then begin to sort through it to find and isolate the parts that we want. In this case we will add some code to loop through our properties and find the updated and name properties.
function parseResponse (response) {
let parsedResponse = JSON.parse(response);
parsedResponse = parsedResponse['search'];
for (let prop in parsedResponse) {
if (prop === 'updated') {
// do stuff with 'updated'
}
if (prop === 'name') {
// do stuff with 'name'
}
}
}
Because we want to return a result we are going to add a variable updated and names which will hold the values that we pull out of the string until we are ready to return them. Now that we have our loop and our temporary variables we can go ahead and pull the updated value out of our data and place it in the updated variable.
function parseResponse (response) {
let parsedResponse = JSON.parse(response),
updated = '',
names = [];
parsedResponse = parsedResponse['search'];
for (let prop in parsedResponse) {
if (prop === 'updated') {
updated = parsedResponse[prop];
}
if (prop === 'name') {
// do stuff with 'name'
}
}
}
With our updated value squared away we can jump into our names. Since you listed the format ['%name%', '%name%', '%name%'] first I am going to go ahead and show you how to do it this way. Here we are going to grab the property name, iterate through the names, grab the tag property, and then add the %s before pushing it to our names temporary variable.
function parseResponse (response) {
let parsedResponse = JSON.parse(response),
updated = '',
names = [];
parsedResponse = parsedResponse['search'];
for (let prop in parsedResponse) {
if (prop === 'updated') {
updated = parsedResponse[prop];
}
if (prop === 'name') {
for (let i = 0; i < parsedResponse[prop].length; i++) {
let name = parsedResponse[prop][i].tag;
name = '%' + name + '%';
names.push(name);
}
}
}
}
With everything in place all that is left is to assemble the result. To do so we are going to flatten the array of names, add them to the array, and then add the updated value to the end before returning it. To flatten the array we are going to use the spread operator.
function parseResponse (response) {
let parsedResponse = JSON.parse(response),
updated = '',
names = [];
parsedResponse = parsedResponse['search'];
for (let prop in parsedResponse) {
if (prop === 'updated') {
updated = parsedResponse[prop];
}
if (prop === 'name') {
for (let i = 0; i < parsedResponse[prop].length; i++) {
let name = parsedResponse[prop][i].tag;
name = '%' + name + '%';
names.push(name);
}
}
}
return [...names, updated];
}
With all of that set we can go ahead and call parseResponse() with data1, data2, or data3 and get back a response that looks like so:
let data1 = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"}]}}',
data2 = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"}]}} ',
data3 = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"},{"tag":"Maria"}]}}';
function parseResponse (response) {
let parsedResponse = JSON.parse(response),
updated = '',
names = [];
parsedResponse = parsedResponse['search'];
for (let prop in parsedResponse) {
if (prop === 'updated') {
updated = parsedResponse[prop];
}
if (prop === 'name') {
for (let i = 0; i < parsedResponse[prop].length; i++) {
let name = parsedResponse[prop][i].tag;
name = '%' + name + '%';
names.push(name);
}
}
}
return [...names, updated];
}
console.log(parseResponse(data1));
console.log(parseResponse(data2));
console.log(parseResponse(data3));
Spread operator can be used to flatten the result :
var obj = {"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"},{"tag":"Maria"}]}}
var arr = [...obj.search.name.map(n => `%${n.tag}%`), obj.search.updated]
console.log( arr )
Another alternative could be to extract during parsing :
var arr = [], json = '{"search":{"updated":"2018-11-07","name":[{"tag":"Peter"},{"tag":"Jack"},{"tag":"Maria"}]}}'
JSON.parse(json, (k, v) => v.trim && arr.push(k === 'tag' ? `%${v}%` : v))
console.log( arr )
I am passing json and a key to below function to retrieve its value. The key can be like abc.cde.def nad it can also be like fgh only.
If the keys contain . then it is a nested json and values has to be retrieved accordingly which is happening correctly but if it is a plain json having no nest then it is not working. Printing the length of keysData (in case the key is like fgh) it prints 3 where it should print 1.
function getValueFromJson(jsonInput,keyInput) {
if(keyInput.includes('.')){
var keysData = keyInput.split('.');
}
else {
keysData = keyInput.toString()
}
var jsonHierarchy = jsonInput;
if(parseInt(keysData.length) === parseInt('1')){
console.log(jsonHierarchy)
console.log(keysData )
console.log(jsonHierarchy[keysData ])
jsonHierarchy = jsonHierarchy[keysData ];
}
return jsonHierarchy;
};
Can anyone please help how can I handle this ?
you dont need to check for if(keyInput.includes('.'))
just do keyInput.split('.')
//for Ex.
'abc.defg'.split('.') // result ['abc', 'defg']
'abc'.split('.') // result ['abc']
and also
if(parseInt(keysData.length) === parseInt('1'))
//can be used as
if(keysData.length === 1)
and your complete function should be
function getValueFromJson(jsonInput,keyInput) {
var keysData = keyInput.split('.');
var jsonHierarchy = jsonInput;
keysData.forEach(function(d) {
if(jsonHierarchy)
jsonHierarchy = jsonHierarchy[d];
})
return jsonHierarchy;
};
var jsonData = {
'abc': {
'def': {
'gh': 'value1'
},
'xyz': 'value2'
}
};
function getValueFromJson(jsonInput, keyInput) {
var keysData = keyInput.split('.');
var jsonHierarchy = jsonInput;
keysData.forEach(function(d) {
if (jsonHierarchy)
jsonHierarchy = jsonHierarchy[d];
})
return jsonHierarchy;
};
function get() {
var val = document.getElementById('key').value;
if (val)
console.log(getValueFromJson(jsonData, val));
};
<input id="key" />
<button onclick="get()">Get Value</button>
Convert your string to an array, then your length with show properly.
var keysData = keyInput.split('.')