What is the type of the data returned back from executeScript()

134 views
Skip to first unread message

Debanjan Bhattacharjee

unread,
Mar 17, 2018, 9:22:50 AM3/17/18
to webdriver
Hello Everyone,

Can someone help me to decode the type of the data returned back from executeScript() as below ?

Using Selenium-Java Clients when I retrieve some performance statistics from Chrome Development Tools as follows :

    System.out.println(((JavascriptExecutor)driver).executeScript(scriptToExecute));

I am receiving the following data :

    [{redirectCount=0, encodedBodySize=64518, unloadEventEnd=0, responseEnd=4247.699999992619, domainLookupEnd=2852.7999999932945, unloadEventStart=0, domContentLoadedEventStart=4630.699999994249, type=navigate, decodedBodySize=215670, duration=5709.000000002561, redirectStart=0, connectEnd=3203.5000000032596, toJSON={}, requestStart=3205.499999996391, initiatorType=beacon}]

The JavaDocs of executeScript() mentions :

If the script has a return value (i.e. if the script contains a return statement), then the following steps will be taken:

  • For an HTML element, this method returns a WebElement
  • For a decimal, a Double is returned
  • For a non-decimal number, a Long is returned
  • For a boolean, a Boolean is returned
  • For all other cases, a String is returned.
  • For an array, return a List<Object> with each object following the rules above. We support nested lists.
  • For a map, return a Map<String, Object> with values following the rules above.
  • Unless the value is null or there is no return value, in which null is returned
Any suggestions/pointer will be helpful.

Thanks and Regards
Debanjan-B

David

unread,
Mar 18, 2018, 2:33:33 PM3/18/18
to webdriver
This is already cross posted here: https://groups.google.com/forum/#!topic/selenium-users/lN2Ld3oN2ws. Perhaps best to respond in the other post.

darrell grainger

unread,
Mar 18, 2018, 6:01:28 PM3/18/18
to webdriver
If you attempt to print a Java object, it will call the toString() method. So if the executeScript() returns a WebElement, it will call the toString() method of the WebElement. WebElement is an interface. The actual implementation would be RemoteWebElement. You can find the source code for WebElement at https://github.com/SeleniumHQ/selenium/blob/master/java/client/src/org/openqa/selenium/remote/RemoteWebElement.java. If you look at this source code you will see the toString() method.

On the other hand, if it is a Double or a Long, then it will call the toString() method for those Java objects. 

Bottom line, you should know what the javascript is returning and use it based on what you know it will be. For example, if the javascript was something like:

return document.querySelector("body");

then it will be returning a WebElement. So I could do something like:

WebElement webelement = ((JavascriptExecutor)driver).executeScript("return document.querySelector("body");");

then I can use webelement just like any other WebElement.

David

unread,
Mar 19, 2018, 3:13:14 PM3/19/18
to webdriver
Darrell, I believe the OP gave the code snippet to show what he/she was dumping out in terms of data structure like dumping out JSON string before you parse it as an object for debugging. Because the OP isn't sure what data type it would be.

I remember similar before with work I've done that it gets a little tricky/confusing with the casting when what is returned isn't basic data type (string/number) nor WebElement, but like an array or a hash/map/dictionary.

darrell grainger

unread,
Mar 20, 2018, 8:34:24 AM3/20/18
to webdriver
The point I was trying to making is that it can be one of eight different datatypes. You need to know what the javascript is returning in order to know which of the eight different datatypes it would be. For example, document.querySelector("css selector goes here"); will return a WebElement (a single HTML element). Where as document.querySelectorAll("css selector goes here"); will return a list of HTML elements. In Java this would be List<WebElement>.

If you don't understand javascript and Java enough to make this comparison then you need to learn this. There are literally dozens of different possible results from a javascript execution. So it would be too difficult to enumerate all of them.

Debanjan Bhattacharjee

unread,
Mar 26, 2018, 4:26:31 AM3/26/18
to webd...@googlegroups.com
@Darrell Grainger and @David

Thanks a lot for all your valuable inputs, suggestions and your valuable time. Your inputs helped me immensely to come to a conclusion. 

However in the selenium-users thread @KrishnanMahadevan suggestion to " try printing it's type via get class() " nailed all the confusion.  It's a "class java.util.ArrayList".

But @JimEvans interpretation and detailed explanation was amazing where he mentioned as follows :

The data being returned is an array, as indicated by the square brackets (“[]”). Inside the array is an object, indicated by curly braces (“{}”). When the Java language bindings parse that returned value, it should be a List<Object>, where the zeroth element will be a Map<String, Object>. You’ll need to cast things accordingly to resolve the types in your Java code. 

There are two approaches : 

1. Treat the dump as an array and put the first set into a Map as follows:

     System.out.println(((JavascriptExecutor)driver).executeScript(scriptToExecute).getClass());
     List<Object> list = (List<Object>)((JavascriptExecutor)driver).executeScript(scriptToExecute);
     System.out.println(list.size());
     for (int i=0;i<list.size();i++)
     System.out.println(list.get(i));
     Map<String, Object> map = (Map<String, Object>)(list.get(0));
        for ( Map.Entry<String, ?> entry : map.entrySet()) 
        {
            System.out.println(entry.getKey() + " value is " + entry.getValue());
        }

2.  Strips off the  "[{", "}]", trims-off the error prone entries and creates/prints the Map :

    String netData = ((JavascriptExecutor)driver).executeScript(scriptToExecute).toString();
     System.out.println(netData);
     String my_text = netData.replaceAll ("[\\[\\]{}]", "");
     System.out.println(my_text);
     String[] items = my_text.split(",");
     Map<String, String> my_array = new HashMap<String,String>();

     for (String s: items){

         String[] item = s.split("=");
         if(item.length == 2){
             my_array.put(item[0].trim(), item[1].trim());
         }else{
             System.out.println("Error with: "+ s);
         }
     }
        for ( Map.Entry<String, ?> entry : my_array.entrySet()) 
        {
            System.out.println(entry.getKey() + " value is " + entry.getValue());
        }


Thanks and Regards
Dev




--
You received this message because you are subscribed to a topic in the Google Groups "webdriver" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/webdriver/0pJ4BxFp41Q/unsubscribe.
To unsubscribe from this group and all its topics, send an email to webdriver+unsubscribe@googlegroups.com.
To post to this group, send email to webd...@googlegroups.com.
Visit this group at https://groups.google.com/group/webdriver.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages