JSON Migration Helper¶
A compatibility layer for JSON handling that abstracts away the breaking changes introduced in Vaadin 25, so the same code can run unchanged on Vaadin 14, 23, 24, and 25.
Overview¶
Vaadin 25 changed how the Flow client–server bridge handles JSON values (event data, executeJs arguments, @ClientCallable arguments and return types). Code written against the old API does not compile or run on Vaadin 25, and code written against the new API does not run on Vaadin 14/23/24. The Json Migration Helper provides drop-in replacements that detect the running Vaadin version at runtime and dispatch to the right implementation, letting libraries and add-ons support all four versions from a single source tree.
Features¶
- Zero-effort migration — write once, run on Vaadin 14, 23, 24, and 25.
- Automatic version detection — picks the right JSON-handling strategy from the runtime Vaadin version.
- Drop-in replacement — simple static methods replacing version-specific APIs.
@ClientCallablecompatibility — helpers for JSON arguments and return types on@ClientCallablemethods.JsonSerializerandJsonCodec— versions of these utilities for serializing and deserializing Elemental JSON values.
Installation¶
From the Vaadin Directory¶
Available in the Vaadin Directory.
Maven dependency¶
Release versions are published to Maven Central:
<dependency>
<groupId>com.flowingcode.vaadin</groupId>
<artifactId>json-migration-helper</artifactId>
<version>X.Y.Z</version>
</dependency>
Replace X.Y.Z with the latest released version. Snapshot builds are available from maven.flowingcode.com/snapshots.
JavaDoc is published at javadoc.flowingcode.com.
Usage¶
The helper exposes three usage patterns, in roughly increasing order of intrusiveness:
- Lombok
@ExtensionMethod— the cleanest, treats helpers as if they were methods onElement/DomEvent. - Direct calls to the
JsonMigrationstatic methods. - Instrumentation — for
@ClientCallablemethods that receiveJsonValuearguments.
Using Lombok @ExtensionMethod¶
The JsonMigration class is designed to be used with Lombok's @ExtensionMethod annotation, which makes its static methods callable as if they were instance methods of Element or DomEvent:
import com.flowingcode.vaadin.jsonmigration.JsonMigration;
import lombok.experimental.ExtensionMethod;
@ExtensionMethod(JsonMigration.class)
public class MyComponent extends Div {
public MyComponent() {
getElement().setPropertyJson("property", jsonValue);
getElement().executeJs("console.log($0)", jsonValue)
.then(json -> { ... });
getElement().addEventListener("click", event -> {
JsonObject eventData = event.getEventData();
});
}
}
Returning JSON from @ClientCallable methods¶
When a @ClientCallable method returns a JSON value, wrap the return value in convertToClientCallableResult so it is shaped correctly for the running Vaadin version:
@ClientCallable
public JsonValue getJsonData() {
JsonValue json = ...;
return JsonMigration.convertToClientCallableResult(json);
}
Receiving JSON in @ClientCallable methods¶
If a method receives JsonValue as an argument, it cannot be annotated with @ClientCallable directly because of compatibility issues. Use @LegacyClientCallable instead and enable instrumentation:
@InstrumentedRoute("legacy-view")
public class ViewWithElementalCallables extends Div {
@LegacyClientCallable
public void receiveJson(JsonValue json) {
// ...
}
}
// Register via META-INF/services/com.vaadin.flow.server.VaadinServiceInitListener,
// or use `@SpringComponent` with Spring.
public class ViewInitializerImpl extends InstrumentationViewInitializer {
@Override
public void serviceInit(ServiceInitEvent event) {
registerInstrumentedRoute(ViewWithElementalCallables.class);
}
}
Instrumentation requires the ASM dependency (not provided out-of-the-box in Vaadin 14–23):
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.8</version>
</dependency>
Instrumentation is intrusive
Instrumentation is a complex mechanism. While the affected code might be worth rewriting to avoid it, this path exists to preserve compatibility with existing implementations.
Direct usage¶
The helper methods can also be called directly from the JsonMigration class without Lombok or instrumentation:
import com.flowingcode.vaadin.jsonmigration.JsonMigration;
import elemental.json.Json;
import elemental.json.JsonValue;
// 1. Setting a JSON property
JsonValue json = Json.createObject();
// ... populate json
JsonMigration.setPropertyJson(element, "property", json);
// 2. Executing JavaScript
JsonMigration.executeJs(element, "console.log($0)", "Hello World");
// 3. Getting event data
element.addEventListener("click", event -> {
JsonObject eventData = JsonMigration.getEventData(event);
// ...
}).addEventData("event.detail");
API¶
Key public types exposed by the library:
JsonMigration— the central entry point. Provides static helpers such assetPropertyJson,executeJs,getEventData, andconvertToClientCallableResult.@LegacyClientCallable— replacement for@ClientCallableon methods that receiveJsonValuearguments. Requires instrumentation.@InstrumentedRoute— declarative way to enable instrumentation on a view.InstrumentationViewInitializer— programmatic way to register instrumented routes from aVaadinServiceInitListener.JsonSerializer/JsonCodec— utilities for serializing and deserializing Elemental JSON values across Vaadin versions.
For full signatures and behavior, consult the published JavaDoc.
Source code¶
JsonMigrationHelper on GitHub — distributed under Apache License 2.0.