You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have a custom JS function that takes an JS array parameter (an array of strings). I tried to invoke it from the server side but it failed with this exception:
java.lang.IllegalArgumentException: Can't encode class [Ljava.lang.String; to json
at com.vaadin.flow.internal.JsonCodec.encodeWithoutTypeInfo(JsonCodec.java:208) ~[flow-server-23.4.1.jar:23.4.1]
at com.vaadin.flow.internal.JsonCodec.encodeWithTypeInfo(JsonCodec.java:95) ~[flow-server-23.4.1.jar:23.4.1]
...
This was surprising, as there is a direct and obvious way to convert Java arrays into JSON arrays, assuming the elements themselves are convertible.
Describe the solution you'd like
I would like Element.callJsFunction() and Element.executeJs() to support parameters having any array type for which the element type is supported.
Describe alternatives you've considered
Gross hacks like this:
// This is a workaround for https://github.com/vaadin/flow/issues/20485// Warning: Each occurrence of array parameter $n is replaced with a *distinct* array literalprivatePendingJavaScriptResultexecuteJs(Elementelement, Stringexpression, Serializable... params) {
// InitializefinalList<Serializable> oldParams = Arrays.asList(params);
finalArrayList<Serializable> newParams = newArrayList<>();
finalintoldTotal = oldParams.size();
intnewTotal = oldTotal;
booleanrecurse = false;
// Flatten array elements from oldParams -> newParams, updating expression placeholders as we gofor (intoldIndex = 0, newIndex = 0; oldIndex < oldTotal; oldIndex++, newIndex++) {
finalSerializableparam = oldParams.get(oldIndex);
// If the param is not an array, just add it and proceedif (param == null || !param.getClass().isArray()) {
newParams.add(param);
continue;
}
// Upshift all parameter placeholders after $newIndexfinalintarrayLength = Array.getLength(param);
finalintindexShift = arrayLength - 1;
finalintminShiftable = newIndex + 1;
expression = Pattern.compile("(?<=\\$)[0-9]+(?![0-9])").matcher(expression)
.replaceAll(result -> {
finalintparamIndex = Integer.parseInt(result.group(), 10);
returnparamIndex >= minShiftable ? String.valueOf(paramIndex + indexShift) : result.group();
});
// Replace placeholder $newIndex with JS array literal containing new $placeholdersfinalStringarrayLiteralReplacement = IntStream.range(newIndex, newIndex + arrayLength)
.mapToObj(index -> "\\$" + index).collect(Collectors.joining(", ", "[ ", " ]"));
expression = expression.replaceAll("\\$" + newIndex + "(?![0-9])", arrayLiteralReplacement);
// Add array elements as parameters; if any is an array, then we will need to recursefor (inti = 0; i < arrayLength; i++) {
finalSerializableelem = (Serializable)Array.get(param, i);
recurse |= elem != null && elem.getClass().isArray();
newParams.add(elem);
}
// Update new parameter current index and totalnewIndex += indexShift;
newTotal += indexShift;
}
params = newParams.toArray(newSerializable[newParams.size()]);
// Recurse if needed, then executereturnrecurse ? this.executeJs(element, expression, params) : element.executeJs(expression, params);
}
Additional context
None.
The text was updated successfully, but these errors were encountered:
For a simpler workaround, you can convert your array to a elemental.json.JsonValue and pass that as a parameter since it will then be sent to the browser as-is.
If you're lazy and fine with using a class from com.vaadin.flow.internal, then you can easily convert the array to JSON like this:
Describe your motivation
I have a custom JS function that takes an JS array parameter (an array of strings). I tried to invoke it from the server side but it failed with this exception:
This was surprising, as there is a direct and obvious way to convert Java arrays into JSON arrays, assuming the elements themselves are convertible.
Describe the solution you'd like
I would like
Element.callJsFunction()
andElement.executeJs()
to support parameters having any array type for which the element type is supported.Describe alternatives you've considered
Gross hacks like this:
Additional context
None.
The text was updated successfully, but these errors were encountered: