diff --git a/flow-server/src/main/java/com/vaadin/flow/dom/Element.java b/flow-server/src/main/java/com/vaadin/flow/dom/Element.java index 6775f3c7bc8..9943cfc2a94 100644 --- a/flow-server/src/main/java/com/vaadin/flow/dom/Element.java +++ b/flow-server/src/main/java/com/vaadin/flow/dom/Element.java @@ -17,6 +17,7 @@ import java.io.Serializable; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; @@ -690,6 +691,58 @@ public Element setPropertyBean(String name, Object value) { return setPropertyJson(name, JsonUtils.beanToJson(value)); } + /** + * Sets the given property to the given list of beans or primitive values, + * converted to a JSON array. + *

+ * Note that properties changed on the server are updated on the client but + * changes made on the client side are not reflected back to the server + * unless configured using + * {@link #addPropertyChangeListener(String, String, PropertyChangeListener)} + * or {@link DomListenerRegistration#synchronizeProperty(String)}. + * + * @param + * the type of items in the list + * @param name + * the property name, not null + * @param value + * the property value, not null + * @return this element + */ + public Element setPropertyList(String name, List value) { + if (value == null) { + throw new IllegalArgumentException( + "setProperty(name, Json.createNull()) must be used to set a property to null"); + } + + return setPropertyJson(name, JsonUtils.listToJson(value)); + } + + /** + * Sets the given property to the given map of beans or primitive values, + * converted to a JSON object. + *

+ * Note that properties changed on the server are updated on the client but + * changes made on the client side are not reflected back to the server + * unless configured using + * {@link #addPropertyChangeListener(String, String, PropertyChangeListener)} + * or {@link DomListenerRegistration#synchronizeProperty(String)}. + * + * @param name + * the property name, not null + * @param value + * the property value, not null + * @return this element + */ + public Element setPropertyMap(String name, Map value) { + if (value == null) { + throw new IllegalArgumentException( + "setProperty(name, Json.createNull()) must be used to set a property to null"); + } + + return setPropertyJson(name, JsonUtils.mapToJson(value)); + } + /** * Adds a property change listener which is triggered when the property's * value is updated on the server side. diff --git a/flow-server/src/main/java/com/vaadin/flow/internal/JsonUtils.java b/flow-server/src/main/java/com/vaadin/flow/internal/JsonUtils.java index 38f4d716234..98a2ca78144 100644 --- a/flow-server/src/main/java/com/vaadin/flow/internal/JsonUtils.java +++ b/flow-server/src/main/java/com/vaadin/flow/internal/JsonUtils.java @@ -19,6 +19,7 @@ import java.util.AbstractList; import java.util.Collections; import java.util.EnumSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.BiConsumer; @@ -298,4 +299,42 @@ public static JsonObject beanToJson(Object bean) { throw new RuntimeException("Error converting bean to JSON", e); } } + + /** + * Converts the given list to JSON. + * + * @param list + * the list to convert, not {@code null} + * @return a JSON representation of the bean + */ + public static JsonArray listToJson(List list) { + if (list == null) { + throw new RuntimeException("Cannot convert null to a JSON object"); + } + try { + return Json.instance().parse(objectMapper.writeValueAsString(list)); + } catch (JsonProcessingException e) { + throw new RuntimeException( + "Error converting list to JSON: " + e.getMessage()); + } + } + + /** + * Converts the given map to JSON. + * + * @param map + * the map to convert, not {@code null} + * @return a JSON representation of the bean + */ + public static JsonObject mapToJson(Map map) { + if (map == null) { + throw new RuntimeException("Cannot convert null to a JSON object"); + } + try { + return Json.instance().parse(objectMapper.writeValueAsString(map)); + } catch (JsonProcessingException e) { + throw new RuntimeException( + "Error converting map to JSON: " + e.getMessage()); + } + } } diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/ElementTest.java b/flow-server/src/test/java/com/vaadin/flow/dom/ElementTest.java index fb82104d9b4..d5fce8335ad 100644 --- a/flow-server/src/test/java/com/vaadin/flow/dom/ElementTest.java +++ b/flow-server/src/test/java/com/vaadin/flow/dom/ElementTest.java @@ -10,8 +10,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -50,6 +52,7 @@ import com.vaadin.tests.util.TestUtil; import elemental.json.Json; +import elemental.json.JsonArray; import elemental.json.JsonObject; import elemental.json.JsonValue; import elemental.json.impl.JreJsonObject; @@ -573,6 +576,30 @@ public void propertyRawValues() { Assert.assertEquals(1.0, json.getNumber("number"), 0.0); Assert.assertEquals(2.3, json.getNumber("flt"), 0.0); Assert.assertEquals(4.56, json.getNumber("dbl"), 0.0); + + List list = new ArrayList<>(); + SimpleBean bean1 = new SimpleBean(); + bean1.string = "bean1"; + SimpleBean bean2 = new SimpleBean(); + bean2.string = "bean2"; + list.add(bean1); + list.add(bean2); + element.setPropertyList("p", list); + JsonArray jsonArray = (JsonArray) element.getPropertyRaw("p"); + Assert.assertEquals("bean1", + jsonArray.getObject(0).getString("string")); + Assert.assertEquals("bean2", + jsonArray.getObject(1).getString("string")); + + Map map = new HashMap<>(); + map.put("one", bean1); + map.put("two", bean2); + element.setPropertyMap("p", map); + JsonObject jsonObject = (JsonObject) element.getPropertyRaw("p"); + Assert.assertEquals("bean1", + jsonObject.getObject("one").getString("string")); + Assert.assertEquals("bean2", + jsonObject.getObject("two").getString("string")); } @Test diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/JsonUtilsTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/JsonUtilsTest.java index e364d1fe5a5..bdac74727d2 100644 --- a/flow-server/src/test/java/com/vaadin/flow/internal/JsonUtilsTest.java +++ b/flow-server/src/test/java/com/vaadin/flow/internal/JsonUtilsTest.java @@ -376,4 +376,35 @@ public void beanWithListAndMap() { ((JsonObject) childBeanList.get(1)).getString("childValue")); } + @Test + public void simpleBeanListToJson() { + ArrayList list = new ArrayList<>(); + SimpleBean bean1 = new SimpleBean(); + bean1.string = "bean1"; + SimpleBean bean2 = new SimpleBean(); + bean2.string = "bean2"; + list.add(bean1); + list.add(bean2); + JsonArray json = JsonUtils.listToJson(list); + + Assert.assertEquals("bean1", json.getObject(0).getString("string")); + Assert.assertEquals("bean2", json.getObject(1).getString("string")); + } + + @Test + public void simpleMapToJson() { + Map map = new HashMap<>(); + SimpleBean bean1 = new SimpleBean(); + bean1.string = "bean1"; + SimpleBean bean2 = new SimpleBean(); + bean2.string = "bean2"; + + map.put("one", bean1); + map.put("two", bean2); + JsonObject json = JsonUtils.mapToJson(map); + + Assert.assertEquals("bean1", json.getObject("one").getString("string")); + Assert.assertEquals("bean2", json.getObject("two").getString("string")); + } + }