From e0fa40ca915cf74dd1ca84a4c5a4ab0a84598c88 Mon Sep 17 00:00:00 2001 From: Kyle Aure Date: Tue, 12 May 2026 10:35:18 -0500 Subject: [PATCH 1/4] fix: DS_STORE in root directory --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 231039b97..7cd0fac3e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ .project .idea/ .settings/ -/.DS_Store +.DS_Store bin/ .envrc .vscode/ From f64587e2fd2557609443b8e360d71adc448afd3a Mon Sep 17 00:00:00 2001 From: Kyle Aure Date: Tue, 12 May 2026 11:54:02 -0500 Subject: [PATCH 2/4] test: replicate issue #707 Co-authored-by-AI: IBM Bob (1.109.5+bob1.0.2) --- .../yasson/jsonstructure/Issue707.java | 111 ++++++++++++++++++ .../JsonStructureToParserAdapterTest.java | 65 ++++++++++ 2 files changed, 176 insertions(+) create mode 100644 src/test/java/org/eclipse/yasson/jsonstructure/Issue707.java diff --git a/src/test/java/org/eclipse/yasson/jsonstructure/Issue707.java b/src/test/java/org/eclipse/yasson/jsonstructure/Issue707.java new file mode 100644 index 000000000..c9a9836fb --- /dev/null +++ b/src/test/java/org/eclipse/yasson/jsonstructure/Issue707.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, + * or the Eclipse Distribution License v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +package org.eclipse.yasson.jsonstructure; + +import jakarta.json.bind.annotation.JsonbTypeDeserializer; +import jakarta.json.bind.serializer.DeserializationContext; +import jakarta.json.bind.serializer.JsonbDeserializer; +import jakarta.json.stream.JsonParser; +import java.lang.reflect.Type; +import java.util.Objects; + +/** + * Test resources for Issue #707: YassonParser.isIntegralNumber throws JsonbException + * instead of IllegalStateException. + * + * This replicates the user's scenario where they want to handle both numeric and + * string IDs by catching IllegalStateException when the value is not a number. + */ +public class Issue707 { + + /** + * Simple ID wrapper that can be created from either a long or a string. + */ + public static class RequestId { + private final String value; + + private RequestId(String value) { + this.value = value; + } + + public static RequestId of(long id) { + return new RequestId(String.valueOf(id)); + } + + public static RequestId of(String id) { + return new RequestId(id); + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RequestId requestId = (RequestId) o; + return Objects.equals(value, requestId.value); + } + + @Override + public int hashCode() { + return Objects.hash(value); + } + + @Override + public String toString() { + return "RequestId{" + value + "}"; + } + } + + /** + * Container class that uses a custom deserializer for the ID field. + */ + public static class Request { + private RequestId id; + + @JsonbTypeDeserializer(RequestIdDeserializer.class) + public RequestId getId() { + return id; + } + + public void setId(RequestId id) { + this.id = id; + } + } + + /** + * Custom deserializer that handles both numeric and string IDs. + * This is the exact pattern from the issue report. + */ + public static class RequestIdDeserializer implements JsonbDeserializer { + @Override + public RequestId deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { + RequestId id = null; + try { + // Try to read as a number first + if (parser.isIntegralNumber()) { + id = RequestId.of(parser.getLong()); + } else { + // Not an integral number, but is still a number + id = RequestId.of(parser.getBigDecimal().toString()); + } + } catch (IllegalStateException e) { + id = RequestId.of(parser.getString()); + } + return id; + } + } +} + diff --git a/src/test/java/org/eclipse/yasson/jsonstructure/JsonStructureToParserAdapterTest.java b/src/test/java/org/eclipse/yasson/jsonstructure/JsonStructureToParserAdapterTest.java index d76984e2a..37d4f151e 100644 --- a/src/test/java/org/eclipse/yasson/jsonstructure/JsonStructureToParserAdapterTest.java +++ b/src/test/java/org/eclipse/yasson/jsonstructure/JsonStructureToParserAdapterTest.java @@ -322,4 +322,69 @@ public void testGetArray() { assertEquals("test1, test2", tags); } + /** + * Test for Issue #707: isIntegralNumber() should throw IllegalStateException, not JsonbException + * when called on a non-numeric value. + * + * This test verifies that the user's code pattern from the issue works correctly: + * - When the value is a string, isIntegralNumber() throws IllegalStateException + * - The exception can be caught and the value read as a string + */ + @Test + public void isIntegralNumberThrowsIllegalStateException() { + // Test with string ID - should catch IllegalStateException and handle gracefully + // This test uses fromJsonStructure to exercise JsonStructureToParserAdapter + JsonObjectBuilder objectBuilder = jsonProvider.createObjectBuilder(); + objectBuilder.add("id", "abc123"); + JsonObject jsonObject = objectBuilder.build(); + + YassonJsonb jsonb = (YassonJsonb) JsonbBuilder.create(); + Issue707.Request result = jsonb.fromJsonStructure(jsonObject, Issue707.Request.class); + + assertNotNull(result); + assertNotNull(result.getId()); + assertEquals("abc123", result.getId().getValue()); + } + + /** + * Test for Issue #707: Verify that an integral ID still works correctly. + */ + @Test + public void isIntegralNumberWithNumericValue() { + // Test with numeric ID - should work without throwing any exception + // This test uses fromJsonStructure to exercise JsonStructureToParserAdapter + JsonObjectBuilder objectBuilder = jsonProvider.createObjectBuilder(); + objectBuilder.add("id", 12345); + JsonObject jsonObject = objectBuilder.build(); + + YassonJsonb jsonb = (YassonJsonb) JsonbBuilder.create(); + Issue707.Request result = jsonb.fromJsonStructure(jsonObject, Issue707.Request.class); + + assertNotNull(result); + assertNotNull(result.getId()); + assertEquals("12345", result.getId().getValue()); + } + + /** + * Test for Issue #707: Verify that floating point numbers are handled correctly. + * isIntegralNumber() should return false for non-integral numbers. + * isIntegralNumber() should not throw an exception for floating point numbers. + */ + @Test + public void isIntegralNumberWithFloatingPoint() { + // Test with floating point ID - isIntegralNumber() returns false, + // so the else block handles it as a string + // This test uses fromJsonStructure to exercise JsonStructureToParserAdapter + JsonObjectBuilder objectBuilder = jsonProvider.createObjectBuilder(); + objectBuilder.add("id", 123.45); + JsonObject jsonObject = objectBuilder.build(); + + YassonJsonb jsonb = (YassonJsonb) JsonbBuilder.create(); + Issue707.Request result = jsonb.fromJsonStructure(jsonObject, Issue707.Request.class); + + assertNotNull(result); + assertNotNull(result.getId()); + // The deserializer will read it as a string when isIntegralNumber() returns false + assertEquals("123.45", result.getId().getValue()); + } } From 7d4f553d2e3b679b03b2a87abefcb887b3d92ef4 Mon Sep 17 00:00:00 2001 From: Kyle Aure Date: Tue, 12 May 2026 12:02:18 -0500 Subject: [PATCH 3/4] fix: #707 --- .../internal/jsonstructure/JsonStructureToParserAdapter.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/eclipse/yasson/internal/jsonstructure/JsonStructureToParserAdapter.java b/src/main/java/org/eclipse/yasson/internal/jsonstructure/JsonStructureToParserAdapter.java index f44999bce..3684dd26c 100644 --- a/src/main/java/org/eclipse/yasson/internal/jsonstructure/JsonStructureToParserAdapter.java +++ b/src/main/java/org/eclipse/yasson/internal/jsonstructure/JsonStructureToParserAdapter.java @@ -141,7 +141,9 @@ private JsonNumber getJsonNumberValue() { JsonStructureIterator iterator = iterators.peek(); JsonValue value = iterator.getValue(); if (value.getValueType() != JsonValue.ValueType.NUMBER) { - throw iterator.createIncompatibleValueError(); + throw new IllegalStateException(Messages.getMessage(MessageKeys.NUMBER_INCOMPATIBLE_VALUE_TYPE_OBJECT, + value.getValueType(), + "current value")); } return (JsonNumber) value; } From 89e52562e7061b4d20765edf6c329cc2f103b6b9 Mon Sep 17 00:00:00 2001 From: Kyle Aure Date: Tue, 12 May 2026 13:42:31 -0500 Subject: [PATCH 4/4] fix: feedback changes --- .../internal/jsonstructure/JsonStructureToParserAdapter.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/org/eclipse/yasson/internal/jsonstructure/JsonStructureToParserAdapter.java b/src/main/java/org/eclipse/yasson/internal/jsonstructure/JsonStructureToParserAdapter.java index 3684dd26c..f70210e5f 100644 --- a/src/main/java/org/eclipse/yasson/internal/jsonstructure/JsonStructureToParserAdapter.java +++ b/src/main/java/org/eclipse/yasson/internal/jsonstructure/JsonStructureToParserAdapter.java @@ -141,9 +141,7 @@ private JsonNumber getJsonNumberValue() { JsonStructureIterator iterator = iterators.peek(); JsonValue value = iterator.getValue(); if (value.getValueType() != JsonValue.ValueType.NUMBER) { - throw new IllegalStateException(Messages.getMessage(MessageKeys.NUMBER_INCOMPATIBLE_VALUE_TYPE_OBJECT, - value.getValueType(), - "current value")); + throw new IllegalStateException(iterator.createIncompatibleValueError().getMessage()); } return (JsonNumber) value; }