Access specified attributes of Json for search index in cloudant - json

I have a Json document as:
{
"_id": "3de00db35e6549604c711e7295a1982a",
"_rev": "1-ecba71644d341dfe5cb9abf6dd13b23a",
"dateCreated": "2014-01-29 00:00:00",
"attributeCollection": {
"attributeArray": [
{
"updateable": false,
"lookup": "issuetype",
"issueAttributeDefinitionId": 13,
"attributeType": 1,
"name": "Web Type",
"value": [
"Improper Limitation of Authentication"
]
},
{
"updateable": true,
"lookup": "status",
"issueAttributeDefinitionId": 1,
"attributeType": 4,
"name": "Status",
"value": [
"Access with Right Permission"
]
}
]
},
"hash": "287030d6efa085b5b92b7106c0edb6d7"
}
I want to create search index for document using "name" and "value" ("name" or "value" only). I accessed these attributes by this codes:
for (var i=0; i<doc.attributeCollection.attributeArray.length; i++) {
if (doc.attributeCollection.attributeArray[i].name) {
name = doc.attributeCollection.attributeArray[i].name;
}
if (doc.attributeCollection.attributeArray[i].value) {
value = doc.attributeCollection.attributeArray[i].value;
}
}
It works when i use contentindex = name + " "+ value; the content shows "Web Type Improper Limitation of Authentication". However, if i use value only contentindex = value, it doesn't work, it shows null.
I know that the structure of "value" likes array (array with 1 element) and it doesn't have any attribute name.
How can i access the value properly?
Update:
When i index some cases as:
1. It works
var content=name + " " + value;
index("default", content);
2. It works
index("default", name);
3. It doesn't work
index("default", value);
4.I fixed with by revised the code to get "value" as:
if (doc.attributeCollection.attributeArray[i].value) {
for (var j=0; j<doc.attributeCollection.attributeArray[i].value.length; j++){
value = doc.attributeCollection.attributeArray[i].value[j];
}
}
Or
if (doc.attributeCollection.attributeArray[i].value) {
value = doc.attributeCollection.attributeArray[i].value[0];
}
It works with index("default", value);
However, when i used permutation function as discussed in this post
5. It works
var content= permuteword(name);
for(var k=0; k<content.length; k++){
index("default", content[k], { store : true });
}
6. It doesn't work
var content= permuteword(value);
for(var k=0; k<content.length; k++){
index("default", content[k], { store : true });
}
7. It doesn't work
var content=name + " " +value;
var content1= permuteword(content);
for(var k=0; k<content1.length; k++){
index("default", content1[k], { store : true });
}

I'm not exactly sure I completely understand your question. It sounds like you are creating an index like this:
for (var i=0; i<doc.attributeCollection.attributeArray.length; i++) {
if (doc.attributeCollection.attributeArray[i].name) {
name = doc.attributeCollection.attributeArray[i].name;
}
if (doc.attributeCollection.attributeArray[i].value) {
value = doc.attributeCollection.attributeArray[i].value;
}
index("contentindex", name + " " + value);
}
If this is the case you could try indexing the name and value separately (Update: changed to access each element in the value array):
for (var i=0; i<doc.attributeCollection.attributeArray.length; i++) {
if (doc.attributeCollection.attributeArray[i].name) {
name = doc.attributeCollection.attributeArray[i].name;
index("contentindex", name);
}
if (doc.attributeCollection.attributeArray[i].value) {
for (var j=0; j<doc.attributeCollection.attributeArray[i].value.length; j++) {
value = doc.attributeCollection.attributeArray[i].value[j];
index("contentindex", value);
}
}
}
Then querying by either the name or the value should return the correct result.
Please let me know if I am misunderstanding you question.

Related

Getting values from JSON using appscript

I'm creating two-dimentional array with google appscript using chrome devices users with the JSON response from a directory. I've been able to get values. However, when I try to get recentUsers represented as:
{
"kind": "directory#chromeosdevices",
"chromeosdevices": [
{
"kind": "directory#chromeosdevice",
"etag": "1234567890"
"deviceId": "def456",
"serialNumber": "234567",
"status": "ACTIVE",
"lastSync": "2013-03-05T17:30:04.325Z",
"supportEndDate": "2014-04-05T17:30:04.325Z",
"annotatedUser": "help desk",
"annotatedLocation": "Mountain View help desk Chromebook",
"annotatedAssetId": "1234567890",
"notes": "Loaned from support",
"orderNumber": "1234",
"willAutoRenew": true,
"osVersion": "Browser Version 18.0",
"platformVersion": "Platform Version 1415.2.0",
"firmwareVersion": "Firmware Version 1.2.3.4",
"bootMode": "validated",
"lastEnrollmentTime": "2012-04-05T17:30:04.325Z",
"orgUnitPath": "corp/engineering",
"recentUsers": [
{
"type": "USER_TYPE_MANAGED",
"email": "user#customer.com" //I'm trying to get the most recent user's email
}
],
"activeTimeRanges": [
{
"date": "2012-04-05",
"activeTime": "3600000"
}
],
}
],
"nextPageToken": "abcdefghijkl123"
}
I get an array but I can't get the value. I'm trying to get the most recent user's email. Anyone have experience with appscript? I've tried recentUsers[0].email and recentUser[0]['email']. This is the code I have to far: //I commented where I'm trying to push a value
enter code here
var chromeArgs = {
maxResults: 200,
orderBy: 'annotatedUser',
projection: "FULL"
};
var getChromes = (AdminDirectory.Chromeosdevices.list('XXXXXXXXX', chromeArgs));
var chromes = getChromes.chromeosdevices;
if (chromes && chromes.length > 0) {
Logger.log('Devices:');
//2d array
var wholeValues = [];
for (var i = 0; i < chromes.length; i++){
//create a 1D array first with pushing 0,1,2 elements with a for loop
var value = [];
for (var j = 0; j < 1; j++) {
var chrms = chromes[i];
var recentUser = chrms.recentUsers;
value.push(recentUser[0].email); // Here is where I need help
}
//pushing the value array with [0,1,2] to thw wholeValues array.
wholeValues.push(value);
} // the outer for loop runs five times , so five the 0,1,2 with be pushed in to thewholevalues array by creating wholeValues[0][0],wholeValues[0][1]...till..wholeValues[4][2]
Logger.log(wholeValues); '''
You are very close, the only thing you need to change is to replace the static recentUsers[0] with dynamic recentUsers[j] within the loop
Sample:
function getChromes(){
var chromeArgs = {
maxResults: 200,
orderBy: 'annotatedUser',
projection: "FULL"
};
var getChromes = (AdminDirectory.Chromeosdevices.list('XXXXXXXXX', chromeArgs));
var chromes = getChromes.chromeosdevices;
if (chromes && chromes.length > 0) {
Logger.log('Devices:');
var wholeValues = [];
for (var i = 0; i < chromes.length; i++){
var chrms = chromes[i];
var recentUser = chrms.recentUsers;
var value = [];
for (var j = 0; j < recentUser.length; j++) {
Logger.log(recentUser[j].email);
value.push(recentUser[j].email);
}
wholeValues.push(value);
}
Logger.log(wholeValues);
}
}
Note that you need to specify the iteration limit of the inner loop dynamically j < recentUser.length; instead of j < 1 to account for different quantity of recent users for each chrome device.

How to set one more level in Object of a not predefined item?

The main issue is the following:
Get JSON from the server
Put data to form
Serialize form
Create JSON with correct structure
Send it to the server
I have difficulties on the fourth step, what I've done:
methods: {
onSubmit: function() {
var dataForm = new FormData(this.$refs['form']);
var data = [];
for (var _iterator = dataForm.entries(), _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _Object$assign;
var _Helper = {};
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var _ref2 = _ref,
key = _ref2[0],
val = _ref2[1];
Object.assign(_Helper, (_Object$assign = {}, _Object$assign[key] = val, _Object$assign));
}
}
},
Here you go - a link to the codepen.
As you can see I could create JSON like that:
{"0":"a","1":"b","2":"c","3":"d","4":"e","5":"d"}
However, I need smth like that:
{
"0": {
"text": "a"
},
"1": {
"text": "b"
},
"2": {
"text": "c"
},
"3": {
"text": "d"
},
"4": {
"text": "e"
},
"5": {
"text": "d"
}
}
What Can I do to implement it and also keep the correct structure of my JSON?
To change the format, change in the location it assigns the property value:
Object.assign(data, (_Object$assign = {}, _Object$assign[key] = {text: val}, _Object$assign));
// -------------------------------------------------------------^^^^^^^^^^^
Instead of a string (val), assign the object in the format you want ({text: val}).
Updated CodePen.
If you can use modern (ES6) JavaScript, there's a much shorter notation for that:
var [key, val] = _ref;
Object.assign(data, {[key]: {text: val}});
CodePen here.
Or (because you are using FormData#entries() you do are using modern JS):
var formData = Array.from(new FormData(this.$refs['form']).entries());
var data = Object.assign(...formData.map(([key, val]) => ({[key]: {text: val}})));
console.log(JSON.stringify(data));
Targetting IE10 and above
To target IE10 and above you'll need polyfills. The problem is not the syntax, but the absence of functions like .entries(), that will be added by the polyfills. To use the least amount possible of polyfills, you'll have to iterate the iterator "manually" (kind of like you are already). For more info, check this answer.
You can do the whole construction much more simply:
onSubmit: function () {
const dataForm = new FormData(this.$refs['form']);
const data = {};
for (const i of dataForm.entries()) {
data[i[0]] = { text: i[1] }
}
console.log(JSON.stringify(data));
}

Delete token from SAPUI5 Multi Input Field with Data Binding

in my SAPUI5 app I am using a Multi Input Field with tokens which are bound to a JSON Model. Newly added entries are saved in the JSON Model. However, when deleting a token by pressing the "x" next to the token text, the token disappears from the multi input field. But when adding a new token the deleted one reappears.
How can I ensure that the deleted entry is also deleted from the JSON Model?
This is my current code for adding the token to the model:
multiInputField.addValidator(function(args){
MessageBox.confirm("Do you really want to add Token\"" + args.text + "\"?", {
onClose: function(oAction) {
if (oAction === MessageBox.Action.OK){
var oToken = new Token({key: args.text, text: args.text});
args.asyncCallback(oToken);
var aFields = sap.ui.getCore().getView().getModel("myModel").getProperty("/Tokens");
var oNewFields= {
Tokens: args.text
};
aFields .push(oNewFields);
sap.ui.getCore().getView().getModel("myModel").setProperty("/Tokens", aFields );
sap.ui.getCore().getView().getModel("myModel").refresh();
} else {
args.asyncCallback(null);
}
},
title: "Add Token"
});
return sap.m.MultiInput.WaitForAsyncValidation;
});
I guess we can use "tokenUpdate" event for this.
For example, given that I have this MultiInput in my view:
<MultiInput width="500px" id="multiInput" suggestionItems="{ path: 'dataModel>/data'}" showValueHelp="true" tokenUpdate="onTokenUpdate">
<core:Item key="{dataModel>key}" text="{dataModel>value}"/>
</MultiInput>
then in my controller I can handle this like :
onTokenUpdate: function(oEvent) {
var sType = oEvent.getParameter("type");
if (sType === "removed") {
var sKey = oEvent.getParameter("removedTokens")[0].getProperty("key");
var oModel = this.getView().getModel("dataModel");
var aData = this.getView().getModel("dataModel").getProperty("/data");
for (var i = 0, len = aData.length; i < len; i++) {
var idx;
console.log(sKey + "-" + aData[i].key);
if (aData[i].key === sKey) {
idx = i;
}
}
aData.splice(idx, 1);
oModel.setProperty("/data", aData);
console.log(oModel);
}
}
And this is my json:
{
"data": [
{
"key": "token1",
"value": "token1"
},
{
"key": "token2",
"value": "token2"
}
]
}

Flattening JSON but keep original properties

I am trying to flatten properties (i.e. objects, array) of a JSON object, but keep the original properties the same, and turn non-scalar properties into strings.
(I'm doing this because when I use the flat npm package, arrays/objects are flattened, but object keys are surrounded by '' , like in 'task_status.0.data' and do not get stored into AzureTables). If there is a way to fix that and de-string that, it would be an ok solution as well...)
Here's an example you could run on jsfiddle.net
var obj1 = {
"studentId": "abc",
"task_status": [
{
"status":"Current",
"date":516760078
},
{
"status":"Late",
"date":1516414446
}
],
"student_plan": "n"
}
FlattenJson = function(obj){
keys = Object.keys(obj);
var newObj = {};
for(var i=0; i<keys.length; i++){
var theType = typeof(obj[keys[i]]);
console.log(theType);
if(theType === 'array' || theType === 'object'){
console.log(JSON.stringify(obj[keys[i]]));
newObj[keys[i]] = "\"" + JSON.stringify(obj[keys[i]]) + "\"";
}
newObj[keys[i]] = obj[keys[i]];
}
return newObj;
}
var newObj1 = FlattenJson(obj1);
console.log(newObj1, obj1);
However, the newobj1 contains the same original array, instead of a string. How would I fix this?
UPDATED: Thanks to this you have a solution.
var obj1 = {
"studentId": "abc",
"task_status": [
{
"status":"Current",
"date":516760078
},
{
"status":"Late",
"date":1516414446
}
],
"student_plan": "n"
}
function customToString (obj) {
var str = '{';
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
str += prop + ':"' + obj[prop] + '",';
}
}
return str.replace(/.$/,'') + '}';
}
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;
};
var newObj1 = flattenObject(obj1);
console.log(newObj1, obj1);
document.write(customToString(newObj1));

Trouble build a table from json file under a div

I need to get rather complicate JSON data from (large) JSON file into a table at a specific part of a page. Somehow when I ran my code, nothing happens.
Snap shoot of purchase.json file -
{
"table": {
"purchases": [
{
"First Name": "Joe",
"Last Name": "Jenson",
"Product": "Netbook Computer",
"Price": "356",
"Purchase Date": "04/04/2011",
"Unit Count": "1",
"Type": "Computer",
"Return Date": "05/03/2011",
"Seq. No.": "0"
},
{
"First Name": "Christy",
"Last Name": "Davis",
"Product": "iPad",
"Price": "656",
"Purchase Date": "04/07/2011",
"Unit Count": "1",
"Type": "Computer",
"Return Date": "05/06/2011",
"Seq. No.": "10"
},
{
"First Name": "Justin",
"Last Name": "Gill",
"Product": "Laptop Computer sleeve",
"Price": "699",
"Purchase Date": "04/02/2011",
"Unit Count": "1",
"Type": "Computer Assesory",
"Return Date": "05/01/2011",
"Seq. No.": "20"
}
]
}
}
The html file -
JSON to table
get json file "purchase.json"
Parse the array into a table and load it in AJAXDiv
Table header has to be pulled from the key in the key:value pair found in the JSON.
The JavaScript code I have is -
$(document).ready(function() {
//Retrieve the JSON data from the server using AJAX
$('#AJAXButton').click(function() {
$.getJSON('data/purchase.json', function(data) {
processJSON(data);
});
});
//Process and display the JSON data
function processJSON(jsondata) {
var output = '<table cellpadding="0" cellspacing="0" border="0" class="display" id="example"><thead><tr>';
// retrieve the keys and place into an array
var keys = objKeys(jsonData.table.loans[0]).join("|");
var keyData = splitString(keys);
// print header
for (var i = 0; i < keyData.length; i++)
{
output += "<th>" + keyData[i] + "</th>";
}
output += "</thead></tr><tfoot>";
// print footer
for (var i = 0; i < keyData.length; i++)
{
output += "<th>" + keyData[i] + "</th>";
}
output += "</tfoot></tr><tbody>";
// print content of the json array in tbody
for(var j=0, jj = jsonData.table.loans.length; j < jj; j++)
{
for (var k = 0, kk = keyData.length; k < kk; k++)
{
var current = keyData[k];
output +="<td>" + jsonData.table.loans[j][current] + "</td>";
}
output += "</tr>";
}
output += "</tbody></tr></table>";
//Loop through the Languages
$('#AJAXDiv').html(output);
}
// get json keys
function objKeys(obj)
{
var keys = [];
var i = 0;
for (var z in obj)
{
if (obj.hasOwnProperty(z)) {
keys[i++] = z;
}
}
return keys;
}
// split string into array
function splitString(myString)
{
var mySplitResult = myString.split("|");
return mySplitResult;
}
});
It may be that you have a variable missing, there's
function processJSON(jsondata)
But you later use
jsonData.table.loans[0] //etc....
I suggest using a debugger like Firebug or DevTools, it makes problems like this much easier to catch.
You can also use this library: Json-To-Html-Table
I use this script that i coded my self, it really builds any json table from a mysql result
o whatever the MySQL is outputting, you can rename the column names with your own labels, by the output order. Also if you give none, the default names will be generated.
It used the $post Jquery plugin-in which you can add easly with 1 line of code.
all you need is the div with table_result:
function dyna_query(label){
$.post("your_mysql_query.php",{post_limit:15},function(e){
if(e=="fail"|| e=="" ||e=="[]"){return;}
var obj=JSON.parse(e);
//get default column names based on the associative object JSON
var column_n=Object.keys(obj[0]).length/2;
var c_names=Object.keys(obj[0]).splice(column_n,column_n);
//if there are labels, then these will replace others.
if( label){c_names=label.split(",");}
var table_row="";
//initialize table
var table_format="<table border=0><tr>";
for(var r=0; r<c_names.length;r++){
table_row+="<td class=table_h>"+c_names[r]+"</td>";}
table_row+="</tr>";
for(var i=0; i<obj.length;i++){table_row+="<tr>";
for(var c=0; c<c_names.length;c++){table_row+="<td class='table_bb'>"+obj[i][c]+" </td>";}table_row+="</tr>";}
//get all the other fields and rows
table_format+=table_row+"</table>";
//buld the html for the div with the id table_result
$("#table_result").html(table_format);
});
}
now simply call dyna_query("c1, c2, c3"); //renames default column names
or
dyna_query(); for full output with default labels