I would like to execute an OQL query in VisualVM (v1.4.4) to retrieve the (non-static) field names for an object.
The OQL documentation describes heap.findClass(className). This returns an object which includes a fields property (an array of field names).
When I execute the following OQL...
heap.findClass('java.io.ByteArrayInputStream').fields;
... it returns an array of 4 field objects (ByteArrayInputStream has 4 fields - buf, count, mark, and pos - I am assuming these are what are being returned):
org.netbeans.lib.profiler.heap.HprofField#56de8c
org.netbeans.lib.profiler.heap.HprofField#56de95
org.netbeans.lib.profiler.heap.HprofField#56de9e
org.netbeans.lib.profiler.heap.HprofField#56dea7
If I then try to manipulate this array, for example to access each field's name and signature properties (as described in the OQL docs), I get no results. I can't even get the length of the array. For example:
heap.findClass('java.io.ByteArrayInputStream').fields.length;
and:
heap.findClass('java.io.ByteArrayInputStream').fields[0];
Both of the above statements return <no results>.
What am I doing wrong? Probably something basic. I not very familiar with JavaScript - or with how data is displayed in VisualVM, for that matter.
You need to use map() function. The following OQL retrieves the field names of ByteArrayInputStream class:
select map(heap.findClass('java.io.ByteArrayInputStream').fields, 'it.name')
Just to add to the very helpful answer from #Tomas - which I have accepted.
Based on his insight, I can also now do things like this in OQL - using a callback instead of an expression string:
map(heap.findClass('java.io.ByteArrayInputStream').fields, function (it) {
var res = '';
res += toHtml(it.name) + " : " + toHtml(it.signature);
return res + "<br>";
});
The above example is trivial, but it opens up more possibilities.
His answer also made me realize where I was going wrong: OQL uses JavaScript expression language - not the exactly the same as JavaScript.
Related
I want to copy form submissions over to a different sheet so that the copied data can be edited without affecting the original submissions.
I have the following code:
function copy2(){
var responses = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("from");
var tracker = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("to");
var lastrow = responses.getLastRow();
var col = responses.getLastColumn();
var row = responses.getRange(lastrow, 1, 1, col).getValues();
tracker.appendRow([null,row[0]]);
Using null in appendRow helps you move the info over to the next column. However, it doesn't quite work with the row[0] array. If I remove the null it works fine, but I want the info copied on a column different that the first one.
Why Ljava.lang.Object?
Because you are using the older Rhino runtime that was written in Java. Hence when something unexpected happens you get a glimpse of the infrastructure GAS is built upon. Now, the java.lang.object is a base class in Java from which other objects, including arrays, are derived.
Since the appendRow method signature's only parameter accepts a one-dimensional array of values, your row[0], which contains an array (see what getvalues method returns), made it to the sheet as a string tag indicating that this was an object at runtime.
What to do in Rhino?
All solutions depend on taking [ null ] as your base array and using concat to append the rest of the first row, something like this: [ null ].concat(row[0]). You can also use push with a simple for loop for better performance.
What to do in V80?
As the other answer mentioned, your best bet is the spread syntax. You can also do a push(...row[0]) to avoid concatenation of arrays (since you immediately use and discard the copy resulting from [ null, ...row[0] ]).
0 See official docs on how to migrate to V8 to take advantage of new language features and improved speed.
Explanation:
The approach of using null is clearly a workaround and not a futureproof
solution. Namely, if you want to start pasting from column 4 you
would have to do [null,null,null,...row[0]] which is not the proper
way to do it in my opinion.
I would advice you to get rid of appendRow and null since you
want to paste the data from the second column onwards. Therefore,
use setValues() instead.
Replace:
tracker.appendRow([null,row[0]]);
with:
tracker.getRange(tracker.getLastRow()+1,2,1,row[0].length).setValues(row);
Complete Solution:
function copy2(){
var responses = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("from");
var tracker = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("to");
var lastrow = responses.getLastRow();
var col = responses.getLastColumn();
var row = responses.getRange(lastrow, 1, 1, col).getValues();
tracker.getRange(tracker.getLastRow()+1,2,1,row[0].length).setValues(row);
}
The row variable contains an array so you should use the spread operator with appendRow
Replace:
tracker.appendRow([null,row[0]]);
with:
tracker.appendRow([null,...row[0]]);
Make sure your project is enabled for Chrome V8 runtime.
Looking for clean way to convert a javascript object containing arrays as values to a search param compatible query string. Serializing an element from each array before moving to the next index.
Using libraries such as querystring or qs, converts the object just fine, but handles each array independently. Passing the resulting string to the server (which I cannot change) causes an error in handling of the items as each previous value is overwritten by the next. Using any kind of array notation in the query string is not supported. The only option I have not tried is a custom sort function, but seems like it would be worse than writing a custom function to parse the object. Any revision to the object that would generate the expected result is welcome as well.
var qs = require("qs")
var jsobj = {
origString:['abc','123'],
newString:['abcd','1234'],
action:'compare'
}
qs.stringify(jsobj,{encode:false})
qs.stringify(jsobj,{encode:false,indices:false})
qs.stringify(jsobj,{encode:false,indices:false,arrayFormat:'repeat'})
Result returned is
"origString=abc&origString=123&newString=abcd&newString=1234&action=compare"
Result desired would be
"origString=abc&newString=abcd&origString=123&newString=1234&action=compare"
I tried reorder your json:
> var jsobj = [{origString: 'abc', newString: 'abcd' }, {origString: '123',
newString: '1234' }, {action:'compare'}]
> qs.stringify(jsobj,{encode:false})
'0[origString]=abc&0[newString]=abcd&1[origString]=123&1[newString]=1234&2[action]=compare'
But I don't know if this is a good alternative for your problem.
Chalk this up to misunderstanding of the application. After spending some more time with the API I realized my mistake, and as posted above by others, order does no matter. Not sure why my first several attempts failed but the question is 'answered'
This answer how to change json object name (key)?
provides a method of replace a name/key in a JSON object but I am running into problems getting it to work.
I am obtaining some fields from a library, such as getColumnTitle etc that have numbers appended that identify which column the Title comes from. Because I need the values associated with a row and have a unique column grouping identifier, the appened numbers cause difficulty at the server side. hence I need to remove the numeric suffix or appended numeric value.
This is what I am trying to do with the code below, however I get a
TypeError: getTaskCellData.remove is not a function
error.
Here is the code.
var getColumnTitle = "hour231";
var getTaskCellData = {"hour231":23,"name":"hello world","other":"fields"};
var alphaTitle = getColumnTitle.replace(/[0-9]/g, '');
getTaskCellData.put(alphaTitle, getTaskCellData.remove(getColumnTitle));
console.log(getTaskCellData)
The answer you linked to is for JAVA, not JavaScript... An object literal, as you have it stored in getTaskCellData, doesn't have remove on its prototype, so you can't use that. Personally I don't think it's worth the code to rename an object's property, simply add a new property holding the same value. If you really insist on renaming, you can do the same and additionally use delete.
var getColumnTitle = "hour231";
var getTaskCellData = {"hour231":23,"name":"hello world","other":"fields"};
var alphaTitle = getColumnTitle.replace(/[0-9]/g, '');
getTaskCellData[alphaTitle] = getTaskCellData[getColumnTitle];
delete getTaskCellData[getColumnTitle];
console.log(getTaskCellData)
Forgive me if this isn't the right platform to ask this question. And let me preface that I'm a designer with very little API and javascript experience.
I'm using the randomUser api to generate a json file or url I can input in Invision's Craft tool for Sketch, so I can input real data in my designs. https://screencast.com/t/jAkwUpUja2. However, it gives the names in lowercase instead of title-case/capitalized.
I'm generating the JSON by typing the endpoints I need in the browser: https://screencast.com/t/E8Cmjk5XSSCk
So, is there a way I can force the api to give me capitalized names? Thanks!
EDIT: here is the JSON url: https://randomuser.me/api/?results=20&nat=us&inc=name,gender,picture&format=pretty
Here is the simplest way to capitalize a string with JS, as far as i know:
// let's assume, that you have stored the lastname as follow:
let last = 'rodney';
To transform the lastname, you apply this pattern:
let capitalizedLast = last[0].toUpperCase() + last.substr(1);
last[0] returns the first letter of the string r.
last.substr(1) gives the rest of the lastname odney
with toUpperCase() you transform the first letter and + will concatenate both to the final result.
You just need to itterate over the results from your API and transform the elements that you needed in that way.
A quick look at the documentation suggests that there might not be a way to get the API to return capitalized names directly. So you're going to have to write some JavaScript to do the job for you.
This code should print out the data to the console with all names capitalized.
It iterates through the items in the result array, goes through all properties of the item's name property and capitalizes them.
The capitalize function gets the first character of the name, converts it to upper case and appends it to the rest of the name.
function capitalize(text) {
return (!text || !text.length) ?
text :
(text[0].toUpperCase() + text.slice(1));
}
$.get("https://randomuser.me/api/?results=20&nat=us&inc=name,gender,picture&format=pretty",
function(data) {
if (!data || !data.results)
return;
data.results.forEach(function(user) {
if (user.name) {
for (var name in user.name) {
user.name[name] = capitalize(user.name[name]);
}
}
});
console.log(data);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Basically I have a complex object that retrieves the GPT API (google publisher tag) with this function:
googletag.pubads().getSlots();
The object value is something like this:
I need to know if there is a way to compare the value of each property with an X value without getting a problem of recursivity (because the object is huge and i need to to that validation several times)
Also, I tried to convert that object into a JSON with JSON.stringify(), and then tried to get the value with a regex, faster, but with this option, I have the problem with Cyclic Object Value.
Any suggestions ?
it's more simple. try it to convert it into an array and later use a filter for comparative with your value.
var objGoogle = {};
var arrayObjectGoogle = [objGoogle];
var filter = arrayObjectGoogle.filter(function(obj){
obj.yourAttr == yourValue; });
this will give you a second array with the values found it. later, index the array for pick up the value do you need.