Java – Create a JSON file using a for each loop and Map – it repeats the first element value across all iterations of the for loop

Create a JSON file using a for each loop and Map – it repeats the first element value across all iterations of the for loop… here is a solution to the problem.

Create a JSON file using a for each loop and Map – it repeats the first element value across all iterations of the for loop

For each of the loops below, do not add all six values in the list. Instead, it just repeats the first value 6 times. Also a JSON file created with the same input.

Note: I also mentioned this link, but didn’t get the expected output. Javascript each loop over JSON only getting first element?

The next steps are,
1. Find the tr element and read the data one by one
2. Map is also used to store these values when reading
3. Add the mapped values to the Jason array.

Below is my code

public static void GetPercentageValue(String locatorType, String locatorValue) throws FileNotFoundException
{
    locatorType="xpath";
    locatorValue="//div[@class='content shadow']/div/child::table[1]/tbody/tr";
    List<WebElement>  tableRows=findTheElements(locatorType,locatorValue);
    for(WebElement tablerow : tableRows)
    {
        Map map = new LinkedHashMap(tableRows.size());
        row=row+1;
        String rowKeys=tablerow.findElement(By.xpath("//div[@class='content shadow']/div/child::table[1]/tbody/tr['"+row+"']/td[1]")).getText();
        String price=tablerow.findElement(By.xpath("//div[@class='content shadow']/div/child::table[1]/tbody/tr['"+row+"']//input")).getAttribute("value");
        System.out.println("RowDesc & Price: "+rowKeys+" "+price);
        map.put(rowKeys, price);
        jArr.add(map);
    }
    jaObj.put("Values", jArr);
     PrintWriter pWriter = new PrintWriter(mbsDataPath1);
     pWriter.write(jaObj.toJSONString());
     pWriter.flush();
     pWriter.close();
}

The expected output should be:

RowDesc & Price: <80.000            0
RowDesc & Price: 80.000-150.000     2
RowDesc & Price: 150.000-300.000    10
RowDesc & Price: 300.000-500.000    15
RowDesc & Price: >500.000           18

The actual output of the code above is:

RowDesc & Price: <80.000 0
RowDesc & Price: <80.000 0
RowDesc & Price: <80.000 0
RowDesc & Price: <80.000 0
RowDesc & Price: <80.000 0

Solution

The workaround is simple. Your XPATH is incorrect

String rowKeys=tablerow.findElement(By.xpath("//div[@class='content shadow']/div/child::table[1]/tbody/tr['"+row+"']/td[1]")).getText();
String price=tablerow.findElement(By.xpath("//div[@class='content shadow']/div/child::table[1]/tbody/tr['"+row+"']//input")).getAttribute("value");

How you pass the row variable is critical!

You pass it as a string (in the context of Xpath) instead of a number.

Let’s assume row=1

Your XPath looks like this:

String rowKeys=tablerow.findElement(By.xpath("//div[@class='content shadow']/div/child::table[1]/tbody/tr['1']/td[1]")).getText();

Do you see it now? You create tr[‘1’] instead of tr[1] and are – it really matters.
If you pass it as tr['1'], then you will match all tr elements, not a specific index. It makes Selenium always match the first element in all tr lists!

Just change Xpath to:

String rowKeys=tablerow.findElement(By.xpath("//div[@class='content shadow']/div/child::table[1]/tbody/tr["+row+"]/td[1]")).getText();
String price=tablerow.findElement(By.xpath("//div[@class='content shadow']/div/child::table[1]/tbody/tr["+row+"]//input")).getAttribute("value");

Related Problems and Solutions