From 377953ecc6b9d50f1c215262094f4eb344495d13 Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Tue, 9 Jun 2026 11:17:15 -0400 Subject: [PATCH 1/2] Fix for Gestbook Response parsing --- .../12446-fix-guestbook-response-parsing.md | 3 +++ scripts/api/data/guestbook-test-response.json | 4 ++++ scripts/api/data/guestbook-test.json | 7 +++++++ .../iq/dataverse/util/json/JsonParser.java | 11 +++++++++-- .../edu/harvard/iq/dataverse/api/FilesIT.java | 3 ++- .../java/edu/harvard/iq/dataverse/api/UtilIT.java | 4 +++- .../iq/dataverse/util/json/JsonParserTest.java | 15 +++++++++++++-- 7 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 doc/release-notes/12446-fix-guestbook-response-parsing.md diff --git a/doc/release-notes/12446-fix-guestbook-response-parsing.md b/doc/release-notes/12446-fix-guestbook-response-parsing.md new file mode 100644 index 00000000000..f9102cdb260 --- /dev/null +++ b/doc/release-notes/12446-fix-guestbook-response-parsing.md @@ -0,0 +1,3 @@ +## Bug ## + +Guestbook response parsing now allows a textarea value to be a string along with an array. diff --git a/scripts/api/data/guestbook-test-response.json b/scripts/api/data/guestbook-test-response.json index df08b52ff6a..18fd79f9f0f 100644 --- a/scripts/api/data/guestbook-test-response.json +++ b/scripts/api/data/guestbook-test-response.json @@ -11,6 +11,10 @@ { "id": @QID3, "value": "Yellow" + }, + { + "id": @QID4, + "value": "Text area with a string instead of an array" } ] } diff --git a/scripts/api/data/guestbook-test.json b/scripts/api/data/guestbook-test.json index 710192b510a..f0138e81351 100644 --- a/scripts/api/data/guestbook-test.json +++ b/scripts/api/data/guestbook-test.json @@ -44,6 +44,13 @@ "displayOrder": 3 } ] + }, + { + "question": "Address", + "required": false, + "displayOrder": 1, + "type": "textarea", + "hidden": false } ] } diff --git a/src/main/java/edu/harvard/iq/dataverse/util/json/JsonParser.java b/src/main/java/edu/harvard/iq/dataverse/util/json/JsonParser.java index 2dfbdef17a2..7f3db716456 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/json/JsonParser.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/json/JsonParser.java @@ -659,8 +659,15 @@ public GuestbookResponse parseGuestbookResponse(JsonObject obj, GuestbookRespons throw new JsonParseException(BundleUtil.getStringFromBundle("access.api.requestAccess.failure.guestbookresponseQuestionIdNotFound", List.of(cqId.toString()))); } else if (cq.getQuestionType().equalsIgnoreCase("textarea")) { String lineFeed = String.valueOf((char) 10); - JsonArray jsonArray = answer.getJsonArray("value"); - List lines = jsonArray.getValuesAs(JsonString.class); + List lines = new ArrayList<>(); + try { + // Assume it's an array but fall back to string if it isn't + JsonArray jsonArray = answer.getJsonArray("value"); + lines = jsonArray.getValuesAs(JsonString.class); + } catch (Exception ex) { + // if not an array try to get a string and add it to the list + lines.add(answer.getJsonString("value")); + } response = lines.stream().map(JsonString::getString).collect(Collectors.joining(lineFeed)); } else if (cq.getQuestionType().equalsIgnoreCase("options")) { String option = answer.getString("value"); diff --git a/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java b/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java index a4d6d9a1ba4..d802fe2049f 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java @@ -3874,7 +3874,6 @@ public void testUpdateWithEmptyFieldsAndVersionCheck() throws InterruptedExcepti @Test public void testDownloadFileWithGuestbookResponse() throws IOException, JsonParseException { msgt("testDownloadFileWithGuestbookResponse"); - UtilIT.enableSetting(SettingsServiceBean.Key.FilePIDsEnabled); // Create superuser Response createUserResponse = UtilIT.createRandomUser(); assertEquals(200, createUserResponse.getStatusCode()); @@ -3948,6 +3947,8 @@ public void testDownloadFileWithGuestbookResponse() throws IOException, JsonPars uploadResponse.prettyPrint(); uploadResponse.then().assertThat().statusCode(OK.getStatusCode()); Integer fileId3 = JsonPath.from(uploadResponse.body().asString()).getInt("data.files[0].dataFile.id"); + + UtilIT.enableSetting(SettingsServiceBean.Key.FilePIDsEnabled); JsonObjectBuilder json4 = Json.createObjectBuilder().add("description", "my description4").add("directoryLabel", directoryLabel).add("categories", Json.createArrayBuilder().add("Data")); uploadResponse = UtilIT.uploadFileViaNative(datasetId.toString(), "src/main/webapp/resources/images/Robot-Icon_2.png", json4.build(), ownerApiToken); uploadResponse.then().assertThat().statusCode(OK.getStatusCode()); diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index 8fd2fbed516..8550b24b439 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -5596,6 +5596,7 @@ public static Guestbook createRandomGuestbook(String ownerAlias, String persiste gb.getCustomQuestions().get(0).setId(jsonPath.getLong("data.customQuestions[0].id")); gb.getCustomQuestions().get(1).setId(jsonPath.getLong("data.customQuestions[1].id")); gb.getCustomQuestions().get(2).setId(jsonPath.getLong("data.customQuestions[2].id")); + gb.getCustomQuestions().get(3).setId(jsonPath.getLong("data.customQuestions[3].id")); // Add the Guestbook to the Dataset if (persistentId != null) { @@ -5615,6 +5616,7 @@ public static String generateGuestbookResponse(Guestbook gb) throws IOException return guestbookAsJson.replace("@ID", gb.getId().toString()) .replace("@QID1", cqIDs.get(0).toString()) .replace("@QID2", cqIDs.get(1).toString()) - .replace("@QID3", cqIDs.get(2).toString()); + .replace("@QID3", cqIDs.get(2).toString()) + .replace("@QID4", cqIDs.get(3).toString()); } } diff --git a/src/test/java/edu/harvard/iq/dataverse/util/json/JsonParserTest.java b/src/test/java/edu/harvard/iq/dataverse/util/json/JsonParserTest.java index cc78dfbc97c..262aa38d5d0 100644 --- a/src/test/java/edu/harvard/iq/dataverse/util/json/JsonParserTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/util/json/JsonParserTest.java @@ -113,6 +113,13 @@ public class JsonParserTest { "displayOrder": 3 } ] + }, + { + "question": "Address", + "required": false, + "displayOrder": 3, + "type": "textarea", + "hidden": false } ] } @@ -792,7 +799,7 @@ public void testGuestbook() throws JsonParseException { Guestbook gb = new Guestbook(); gb = sut.parseGuestbook(jsonObj, gb); assertEquals(true, gb.isEnabled()); - assertEquals(3, gb.getCustomQuestions().size()); + assertEquals(4, gb.getCustomQuestions().size()); assertEquals(4, gb.getCustomQuestions().get(2).getCustomQuestionValues().size()); assertEquals("Purple", gb.getCustomQuestions().get(2).getCustomQuestionValues().get(3).getValueString()); assertEquals(3, gb.getCustomQuestions().get(2).getCustomQuestionValues().get(3).getDisplayOrder()); @@ -827,6 +834,10 @@ public void testGuestbookResponse() throws JsonParseException { { "id": 3, "value": "Yellow" + }, + { + "id": 4, + "value": "Text area with a string instead of an array" } ] } @@ -850,7 +861,7 @@ public void testGuestbookResponse() throws JsonParseException { guestbookResponse.setGuestbook(gb); jsonObj = JsonUtil.getJsonObject(guestbookResponseJson); GuestbookResponse gbr = sut.parseGuestbookResponse(jsonObj, guestbookResponse); - assertTrue(gbr.getCustomQuestionResponses().size() == 3); + assertTrue(gbr.getCustomQuestionResponses().size() == 4); // Test missing required question response try { From 3354a7a38958acc63d907d62ba95ae4fef22f807 Mon Sep 17 00:00:00 2001 From: Steven Winship <39765413+stevenwinship@users.noreply.github.com> Date: Tue, 9 Jun 2026 13:46:58 -0400 Subject: [PATCH 2/2] fix test by ordering the custom questions by displayOrder --- scripts/api/data/guestbook-test.json | 2 +- src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/api/data/guestbook-test.json b/scripts/api/data/guestbook-test.json index f0138e81351..b83a130c888 100644 --- a/scripts/api/data/guestbook-test.json +++ b/scripts/api/data/guestbook-test.json @@ -48,7 +48,7 @@ { "question": "Address", "required": false, - "displayOrder": 1, + "displayOrder": 3, "type": "textarea", "hidden": false } diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index 8550b24b439..c0d6a19f99b 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -5611,7 +5611,9 @@ public static String generateGuestbookResponse(Guestbook gb) throws IOException String guestbookAsJson = new String(Files.readAllBytes(Paths.get(guestbookJson.getAbsolutePath()))); List cqIDs = new ArrayList<>(); - gb.getCustomQuestions().stream().forEach(cq -> cqIDs.add(cq.getId())); + // Try to match the IDs. This is no easy task as the custom questions are not added to the db in order by id. + // We will use "displayOrder" to help match them up + gb.getCustomQuestions().stream().sorted(Comparator.comparing(CustomQuestion::getDisplayOrder)).forEach(cq -> cqIDs.add(cq.getId())); return guestbookAsJson.replace("@ID", gb.getId().toString()) .replace("@QID1", cqIDs.get(0).toString())