基于Vaadin框架为DAO类的JSON文本字段创建视图绑定器
Alright, let's work through building a view binder that connects your DAO's JSON-storing field (backed by that JsonObject class) to Vaadin UI components. We'll cover both displaying the JSON data and setting up editable bindings, since Vaadin's data system works great for both use cases.
1. Build a Custom Component to Render JsonObject
Since your JsonObject can hold different data types (objects, arrays, strings, numbers, etc.), we'll make a reusable component that dynamically renders the right UI based on which field is populated.
import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.component.listbox.ListBox; import java.util.Map; public class JsonDisplayComponent extends VerticalLayout { public JsonDisplayComponent() { setSpacing(true); setPadding(true); } public void setJsonObject(JsonObject jsonObject) { // Clear existing components first removeAll(); // Show raw JSON if available if (jsonObject.getOriginal() != null) { TextField originalField = new TextField("Raw JSON"); originalField.setValue(jsonObject.getOriginal()); originalField.setReadOnly(true); originalField.setWidthFull(); add(originalField); } // Render based on the non-null field if (jsonObject.getJsonString() != null) { add(createLabeledField("String Value", jsonObject.getJsonString())); } else if (jsonObject.getJsonNumber() != null) { add(createLabeledField("Number Value", jsonObject.getJsonNumber().toString())); } else if (jsonObject.getJsonFloat() != null) { add(createLabeledField("Float Value", jsonObject.getJsonFloat().toString())); } else if (jsonObject.getJsonBoolean() != null) { add(createLabeledField("Boolean Value", jsonObject.getJsonBoolean().toString())); } else if (jsonObject.getJsonArray() != null) { ListBox<String> arrayList = new ListBox<>(); arrayList.setItems(jsonObject.getJsonArray().stream() .map(obj -> obj.getOriginal() != null ? obj.getOriginal() : obj.toString()) .toList()); add(new TextField("JSON Array").setReadOnly(true), arrayList); } else if (jsonObject.getJsonObjects() != null) { VerticalLayout objectLayout = new VerticalLayout(); objectLayout.add(new TextField("JSON Object").setReadOnly(true)); for (Map.Entry<String, JsonObject> entry : jsonObject.getJsonObjects().entrySet()) { TextField keyField = new TextField("Key"); keyField.setValue(entry.getKey()); keyField.setReadOnly(true); JsonDisplayComponent valueComponent = new JsonDisplayComponent(); valueComponent.setJsonObject(entry.getValue()); objectLayout.add(keyField, valueComponent); } add(objectLayout); } } private TextField createLabeledField(String label, String value) { TextField field = new TextField(label); field.setValue(value); field.setReadOnly(true); field.setWidthFull(); return field; } }
2. Set Up the Binder with Data Binding
To connect your DAO's JsonObject field to Vaadin's Binder, we'll use either a simple value provider for display-only cases or a converter for editable scenarios.
Display-Only Binding
If you just need to show the JSON data without editing:
import com.vaadin.flow.data.binder.Binder; // Assume your DAO class looks like this public class MyDao { private JsonObject jsonData; // Getters and setters public JsonObject getJsonData() { return jsonData; } public void setJsonData(JsonObject jsonData) { this.jsonData = jsonData; } } // In your View class public class MyDaoView extends VerticalLayout { private Binder<MyDao> binder = new Binder<>(MyDao.class); private JsonDisplayComponent jsonDisplay = new JsonDisplayComponent(); public MyDaoView() { add(jsonDisplay); // Bind the JsonObject field to our custom component binder.forField(jsonDisplay) .withNullRepresentation(new JsonObject("{}")) // Default empty JSON .bind(MyDao::getJsonData, (dao, json) -> jsonDisplay.setJsonObject(json)); // Load your DAO data (replace with your actual data fetch logic) MyDao dao = loadDaoFromDatabase(); binder.readBean(dao); } }
Editable Binding (With Raw JSON Input)
If you want users to edit the JSON via a raw text input, add a TextArea and use a converter to handle the string-to-JsonObject conversion:
import com.vaadin.flow.component.textfield.TextArea; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.data.converter.Converter; import com.vaadin.flow.data.binder.Result; import com.vaadin.flow.data.binder.ValueContext; public class MyEditableDaoView extends VerticalLayout { private Binder<MyDao> binder = new Binder<>(MyDao.class); private TextArea rawJsonInput = new TextArea("Edit Raw JSON"); public MyEditableDaoView() { rawJsonInput.setWidthFull(); rawJsonInput.setHeight("300px"); add(rawJsonInput); // Create a converter between raw JSON string and JsonObject Converter<String, JsonObject> jsonConverter = new Converter<>() { @Override public Result<JsonObject> convertToModel(String value, ValueContext context) { if (value == null || value.isBlank()) { return Result.ok(new JsonObject("{}")); } try { return Result.ok(new JsonObject(value)); } catch (Exception e) { return Result.error("Invalid JSON format - please check your input"); } } @Override public String convertToPresentation(JsonObject value, ValueContext context) { return value != null ? value.getOriginal() : "{}"; } }; // Bind the TextArea to the DAO's JsonObject field binder.forField(rawJsonInput) .withConverter(jsonConverter) .bind(MyDao::getJsonData, MyDao::setJsonData); // Load data and add save functionality MyDao dao = loadDaoFromDatabase(); binder.readBean(dao); Button saveBtn = new Button("Save", click -> { if (binder.writeBeanIfValid(dao)) { saveDaoToDatabase(dao); // Replace with your save logic Notification.show("JSON saved successfully!"); } }); add(saveBtn); } }
3. Leverage the VIEW Callback for Auto-Updates
Your JsonObject has a name(VIEW v) method to set a view reference. To make the UI automatically update when the JsonObject changes programmatically, modify the class to trigger notifications:
public class JsonObject { // ... existing fields and constructor ... private VIEW view; // Notify the view when data changes private void notifyViewChanged() { if (view != null) { // Cast to our custom component and refresh ((JsonDisplayComponent) view).setJsonObject(this); } } // Override setters to trigger notifications public void setJsonString(String jsonString) { this.jsonString = jsonString; notifyViewChanged(); } // Repeat this pattern for other setters (jsonNumber, jsonBoolean, etc.) // ... existing getters and setters ... }
Now whenever you update the JsonObject's data, the UI will refresh automatically without extra code.
内容的提问来源于stack exchange,提问作者Yerbol

