diff --git a/src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java b/src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java index d089878..90fefe5 100644 --- a/src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java +++ b/src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java @@ -466,6 +466,26 @@ private void generateMethodOverride( mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(paramType)); } + localVarIndex++; + } else if (hasJsonValueParams && JsonValue[].class.isAssignableFrom(paramType)) { + // Load the JsonNode[] parameter and create target array + mv.visitVarInsn(Opcodes.ALOAD, localVarIndex); + mv.visitInsn(Opcodes.DUP); + mv.visitInsn(Opcodes.ARRAYLENGTH); + mv.visitTypeInsn(Opcodes.ANEWARRAY, Type.getInternalName(paramType.getComponentType())); + + // Stack before: [SourceArray, TargetArray] + // Stack after: [TargetArray, SourceArray, TargetArray] + mv.visitInsn(Opcodes.DUP_X1); + + // Call JsonMigration.convertToJsonValue(JsonNode[], JsonValue[]) + mv.visitMethodInsn( + Opcodes.INVOKESTATIC, + "com/flowingcode/vaadin/jsonmigration/JsonMigration", + "convertToJsonValue", + "([Ljava/lang/Object;[Lelemental/json/JsonValue;)V", + false); + localVarIndex++; } else { localVarIndex += loadParameter(mv, paramType, localVarIndex); diff --git a/src/main/java/com/flowingcode/vaadin/jsonmigration/JsonMigration.java b/src/main/java/com/flowingcode/vaadin/jsonmigration/JsonMigration.java index a63ac25..f671293 100644 --- a/src/main/java/com/flowingcode/vaadin/jsonmigration/JsonMigration.java +++ b/src/main/java/com/flowingcode/vaadin/jsonmigration/JsonMigration.java @@ -91,6 +91,32 @@ public static JsonValue convertToJsonValue(Object object) { return helper.convertToJsonValue(object); } + /** + * Converts an array of objects into an array of {@code JsonValue} objects. + * + *
+ * This method delegates the conversion to a version-specific helper to handle any differences in + * the serialization process. + * + * @param source the array of objects to convert + * @param target the destination array to be populated with converted {@code JsonValue}s + * @throws NullPointerException if source or target is null + * @throws IllegalArgumentException if the array lengths do not match + * @throws ArrayStoreException if an element in the {@code source} array is converted into a type + * that is not assignable to the runtime component type of the {@code target} array + */ + public static void convertToJsonValue(Object[] source, JsonValue[] target) { + if (source.length != target.length) { + throw new IllegalArgumentException( + String.format("Array length mismatch: source.length=%d, target.length=%d", + source.length, target.length)); + } + + for (int i = 0; i < target.length; i++) { + target[i] = convertToJsonValue(source[i]); + } + } + @SneakyThrows private static Object invoke(Method method, Object instance, Object... args) { return helper.invoke(method, instance, args); diff --git a/src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_ArrayOfJsonObject__V.java b/src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_ArrayOfJsonObject__V.java index 6615966..12efb5b 100644 --- a/src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_ArrayOfJsonObject__V.java +++ b/src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_ArrayOfJsonObject__V.java @@ -19,18 +19,21 @@ */ package com.flowingcode.vaadin.jsonmigration; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.emptyArray; import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; import com.vaadin.flow.component.ClientCallable; import elemental.json.JsonObject; -import org.junit.Assert; +import org.hamcrest.Matchers; public class ClientCallable_ArrayOfJsonObject__V extends BaseClientCallable { @ClientCallable public void test(JsonObject[] arg) { - Assert.assertNotNull(arg); - Assert.assertThat(arg, not(emptyArray())); + assertThat(arg, notNullValue()); + assertThat(arg, not(emptyArray())); + assertThat(arg, Matchers.instanceOf(JsonObject[].class)); trace(); } } diff --git a/src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonObjectVarargs__V.java b/src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonObjectVarargs__V.java index 2a23c5a..aba192b 100644 --- a/src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonObjectVarargs__V.java +++ b/src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonObjectVarargs__V.java @@ -19,18 +19,21 @@ */ package com.flowingcode.vaadin.jsonmigration; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.emptyArray; import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; import com.vaadin.flow.component.ClientCallable; import elemental.json.JsonObject; -import org.junit.Assert; +import org.hamcrest.Matchers; public class ClientCallable_JsonObjectVarargs__V extends BaseClientCallable { @ClientCallable - public void test(JsonObject[] arg) { - Assert.assertNotNull(arg); - Assert.assertThat(arg, not(emptyArray())); + public void test(JsonObject... arg) { + assertThat(arg, notNullValue()); + assertThat(arg, not(emptyArray())); + assertThat(arg, Matchers.instanceOf(JsonObject[].class)); trace(); } } diff --git a/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_ArrayOfJsonObject__V.java b/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_ArrayOfJsonObject__V.java index 3a8d3d1..ac61ee3 100644 --- a/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_ArrayOfJsonObject__V.java +++ b/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_ArrayOfJsonObject__V.java @@ -19,17 +19,20 @@ */ package com.flowingcode.vaadin.jsonmigration; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.emptyArray; import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; import elemental.json.JsonObject; -import org.junit.Assert; +import org.hamcrest.Matchers; public class LegacyClientCallable_ArrayOfJsonObject__V extends BaseClientCallable { @LegacyClientCallable public void test(JsonObject[] arg) { - Assert.assertNotNull(arg); - Assert.assertThat(arg, not(emptyArray())); + assertThat(arg, notNullValue()); + assertThat(arg, not(emptyArray())); + assertThat(arg, Matchers.instanceOf(JsonObject[].class)); trace(); } } diff --git a/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_ArrayOfJsonString__V.java b/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_ArrayOfJsonString__V.java new file mode 100644 index 0000000..e07d31c --- /dev/null +++ b/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_ArrayOfJsonString__V.java @@ -0,0 +1,38 @@ +/*- + * #%L + * Json Migration Helper + * %% + * Copyright (C) 2025 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.flowingcode.vaadin.jsonmigration; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyArray; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import elemental.json.JsonString; +import org.hamcrest.Matchers; + +public class LegacyClientCallable_ArrayOfJsonString__V extends BaseClientCallable { + + @LegacyClientCallable + public void test(JsonString[] arg) { + assertThat(arg, notNullValue()); + assertThat(arg, not(emptyArray())); + assertThat(arg, Matchers.instanceOf(JsonString[].class)); + trace(); + } +} diff --git a/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonObjectVarargs__V.java b/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonObjectVarargs__V.java index 5e7ccfe..2f7b562 100644 --- a/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonObjectVarargs__V.java +++ b/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonObjectVarargs__V.java @@ -19,17 +19,20 @@ */ package com.flowingcode.vaadin.jsonmigration; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.emptyArray; import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; import elemental.json.JsonObject; -import org.junit.Assert; +import org.hamcrest.Matchers; public class LegacyClientCallable_JsonObjectVarargs__V extends BaseClientCallable { @LegacyClientCallable - public void test(JsonObject[] arg) { - Assert.assertNotNull(arg); - Assert.assertThat(arg, not(emptyArray())); + public void test(JsonObject... arg) { + assertThat(arg, notNullValue()); + assertThat(arg, not(emptyArray())); + assertThat(arg, Matchers.instanceOf(JsonObject[].class)); trace(); } } diff --git a/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest.java b/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest.java index 580e17a..56bec9b 100644 --- a/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest.java +++ b/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest.java @@ -79,6 +79,8 @@ private static Object invokeTestMethod(BaseClientCallable instrumented, Object.. protected abstract Object createArrayOfJsonObject(); + protected abstract Object createArrayOfJsonString(); + @Test public void test__V() throws Exception { LegacyClientCallable__V instrumented = @@ -315,6 +317,15 @@ public void test_JsonObject__V() throws Exception { assertTrue(instrumented.hasBeenTraced()); } + @Test + public void test_ArrayOfJsonString__V() throws Exception { + LegacyClientCallable_ArrayOfJsonString__V instrumented = + instrumentClass(LegacyClientCallable_ArrayOfJsonString__V.class).getDeclaredConstructor() + .newInstance(); + invokeTestMethod(instrumented, createArrayOfJsonString()); + assertTrue(instrumented.hasBeenTraced()); + } + @Test public void test_ArrayOfJsonObject__V() throws Exception { LegacyClientCallable_ArrayOfJsonObject__V instrumented = diff --git a/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest24.java b/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest24.java index 2a7c783..812946b 100644 --- a/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest24.java +++ b/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest24.java @@ -22,6 +22,7 @@ import com.vaadin.flow.component.Component; import elemental.json.Json; import elemental.json.JsonObject; +import elemental.json.JsonString; public class LegacyClientCallablesTest24 extends LegacyClientCallablesTest { @@ -46,7 +47,7 @@ protected Object createJsonNumber() { } @Override - protected Object createJsonString() { + protected JsonString createJsonString() { return Json.create("test"); } @@ -65,4 +66,9 @@ protected Object createArrayOfJsonObject() { return new JsonObject[] {createJsonObject(), createJsonObject()}; } + @Override + protected Object createArrayOfJsonString() { + return new JsonString[] {createJsonString(), createJsonString()}; + } + } diff --git a/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest25.java b/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest25.java index 7464a9a..a2ec99f 100644 --- a/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest25.java +++ b/src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest25.java @@ -52,7 +52,7 @@ protected Object createJsonNumber() { } @Override - protected Object createJsonString() { + protected StringNode createJsonString() { return StringNode.valueOf("test"); } @@ -71,4 +71,9 @@ protected Object createArrayOfJsonObject() { return new ObjectNode[] {createJsonObject(), createJsonObject()}; } + @Override + protected Object createArrayOfJsonString() { + return new StringNode[] {createJsonString(), createJsonString()}; + } + }