33
33
import java .util .stream .Stream ;
34
34
35
35
import tools .jackson .core .JacksonException ;
36
+ import tools .jackson .core .JsonGenerator ;
36
37
import tools .jackson .core .json .JsonReadFeature ;
37
38
import tools .jackson .core .type .TypeReference ;
38
39
import tools .jackson .core .util .DefaultPrettyPrinter ;
41
42
import tools .jackson .databind .DeserializationFeature ;
42
43
import tools .jackson .databind .JsonNode ;
43
44
import tools .jackson .databind .ObjectMapper ;
45
+ import tools .jackson .databind .SerializationContext ;
46
+ import tools .jackson .databind .ValueSerializer ;
44
47
import tools .jackson .databind .json .JsonMapper ;
48
+ import tools .jackson .databind .module .SimpleModule ;
45
49
import tools .jackson .databind .node .ArrayNode ;
46
50
import tools .jackson .databind .node .BaseJsonNode ;
47
51
import tools .jackson .databind .node .DoubleNode ;
48
52
import tools .jackson .databind .node .JsonNodeType ;
49
53
import tools .jackson .databind .node .ObjectNode ;
50
54
import tools .jackson .databind .node .ValueNode ;
51
55
56
+ import com .vaadin .flow .component .Component ;
57
+ import com .vaadin .flow .dom .Element ;
58
+ import com .vaadin .flow .dom .Node ;
59
+
52
60
import elemental .json .Json ;
53
61
import elemental .json .JsonArray ;
54
62
import elemental .json .JsonBoolean ;
@@ -71,10 +79,17 @@ public final class JacksonUtils {
71
79
72
80
private static final String CANNOT_CONVERT_NULL_TO_OBJECT = "Cannot convert null to Java object" ;
73
81
74
- private static final ObjectMapper objectMapper = JsonMapper .builder ()
75
- .enable (JsonReadFeature .ALLOW_SINGLE_QUOTES )
76
- .disable (DeserializationFeature .FAIL_ON_NULL_FOR_PRIMITIVES )
77
- .build ();
82
+ private static final ObjectMapper objectMapper = createConfiguredMapper ();
83
+
84
+ private static ObjectMapper createConfiguredMapper () {
85
+ SimpleModule module = new SimpleModule ();
86
+ module .addSerializer (Component .class , new ComponentSerializer ());
87
+ module .addSerializer (Node .class , new NodeSerializer ());
88
+
89
+ return JsonMapper .builder ().enable (JsonReadFeature .ALLOW_SINGLE_QUOTES )
90
+ .disable (DeserializationFeature .FAIL_ON_NULL_FOR_PRIMITIVES )
91
+ .addModule (module ).build ();
92
+ }
78
93
79
94
public static ObjectMapper getMapper () {
80
95
return objectMapper ;
@@ -632,4 +647,63 @@ public static String toFileJson(JsonNode node) throws JacksonException {
632
647
.withObjectNameValueSpacing (Spacing .AFTER ));
633
648
return objectMapper .writer ().with (filePrinter ).writeValueAsString (node );
634
649
}
650
+
651
+ /**
652
+ * Custom Jackson serializer for Component that delegates to NodeSerializer.
653
+ */
654
+ public static class ComponentSerializer extends ValueSerializer <Component > {
655
+ private final NodeSerializer nodeSerializer = new NodeSerializer ();
656
+
657
+ @ Override
658
+ public void serialize (Component component , JsonGenerator gen ,
659
+ SerializationContext serializers ) {
660
+ try {
661
+ if (component != null ) {
662
+ // Delegate to NodeSerializer using the component's element
663
+ nodeSerializer .serialize (component .getElement (), gen ,
664
+ serializers );
665
+ } else {
666
+ gen .writeNull ();
667
+ }
668
+ } catch (Exception e ) {
669
+ throw new RuntimeException ("Failed to serialize Component" , e );
670
+ }
671
+ }
672
+ }
673
+
674
+ /**
675
+ * Custom Jackson serializer for Node types (Element, ShadowRoot) that
676
+ * serializes attached nodes as @v-node references for client-side DOM
677
+ * manipulation.
678
+ */
679
+ @ SuppressWarnings ("rawtypes" )
680
+ public static class NodeSerializer extends ValueSerializer <Node > {
681
+ @ Override
682
+ @ SuppressWarnings ("unchecked" )
683
+ public void serialize (Node node , JsonGenerator gen ,
684
+ SerializationContext serializers ) {
685
+ try {
686
+ if (node != null ) {
687
+ // Serialize attached nodes as @v-node references containing
688
+ // the StateNode ID
689
+ // This allows the client to identify and manipulate the
690
+ // corresponding DOM element
691
+ if (node .getNode ().isAttached ()) {
692
+ gen .writeStartObject ();
693
+ gen .writeNumberProperty ("@v-node" ,
694
+ node .getNode ().getId ());
695
+ gen .writeEndObject ();
696
+ } else {
697
+ // Detached nodes cannot be referenced on the client, so
698
+ // serialize as null
699
+ gen .writeNull ();
700
+ }
701
+ } else {
702
+ gen .writeNull ();
703
+ }
704
+ } catch (Exception e ) {
705
+ throw new RuntimeException ("Failed to serialize Node" , e );
706
+ }
707
+ }
708
+ }
635
709
}
0 commit comments