Repository: OpenRefine/OpenRefine (java)

Issue:
join() of array with nulls throws NullPointerException
As mentioned in https://github.com/OpenRefine/OpenRefine/issues/6521#issuecomment-2104513492

### To Reproduce
Steps to reproduce the behavior:
1. `parseJson("['a',null,'b']".join(',')`

### Current Results
NullPointerException

### Expected Behavior
`"a,,b"` (but because of a different bug it should currently return `"a,b"`



Pull request description:
Fix join() of arrays containing nulls. Fixes #6683
Fixes #6683

Changes proposed in this pull request:
- Fix join() of arrays containing nulls



Patch:
diff --git a/main/src/com/google/refine/expr/functions/arrays/Join.java b/main/src/com/google/refine/expr/functions/arrays/Join.java
index e40e25e0f..917684407 100644
--- a/main/src/com/google/refine/expr/functions/arrays/Join.java
+++ b/main/src/com/google/refine/expr/functions/arrays/Join.java
@@ -76,15 +76,18 @@ public class Join implements Function {
                         int l = a.size();
 
                         for (int i = 0; i < l; i++) {
-                            if (!isFirst) {
-                                sb.append(separator);
+                            Object o = JsonValueConverter.convert(a.get(i));
+                            if (o != null) {
+                                if (!isFirst) {
+                                    sb.append(separator);
+                                }
+                                sb.append(o).toString();
+                                isFirst = false;
                             }
-                            // FIXME: This throws NPE for arrays containing nulls
-                            sb.append(JsonValueConverter.convert(a.get(i)).toString());
-                            isFirst = false;
                         }
                     } else {
                         for (Object o : ExpressionUtils.toObjectList(v)) {
+                            // TODO: Another instance of null being treated differently than empty string
                             if (o != null) {
                                 if (!isFirst) {
                                     sb.append(separator);


Test patch:
diff --git a/main/tests/server/src/com/google/refine/expr/functions/arrays/JoinTests.java b/main/tests/server/src/com/google/refine/expr/functions/arrays/JoinTests.java
index 8453cf7da..08ca4ddae 100644
--- a/main/tests/server/src/com/google/refine/expr/functions/arrays/JoinTests.java
+++ b/main/tests/server/src/com/google/refine/expr/functions/arrays/JoinTests.java
@@ -59,9 +59,9 @@ public class JoinTests extends GrelTestBase {
         parseEval(bindings, new String[] { "['','',''].join('|')", "||" });
 
         // Tests for JSON array
-        // Both of the following tests throw NPEs. First is desired behavior, second is current array behavior
+        // First test below is desired behavior, second is current array behavior
 //        parseEval(bindings, new String[] { "'[null,null,null]'.parseJson().join('|')", "||" } );
-//        parseEval(bindings, new String[] { "'[null,null,null]'.parseJson().join('|')", "" } );
+        parseEval(bindings, new String[] { "'[null,null,null]'.parseJson().join('|')", "" });
         parseEval(bindings, new String[] { "'[\"\",2,3]'.parseJson().join('|')", "|2|3" });
         parseEval(bindings, new String[] { "'[1,2,\"\"]'.parseJson().join('|')", "1|2|" });
         parseEval(bindings, new String[] { "'[\"\",\"\",\"\"]'.parseJson().join('|')", "||" });