+ *
+ *
+ * @see JsonSerializer
+ * @see FieldSelector
+ * @see FieldSelectorHolder
+ */
public class DynamicFieldSerializer extends JsonSerializer {
+ /**
+ * Holder containing the field selector used to determine which fields should be serialized.
+ */
private final FieldSelectorHolder holder;
+ /**
+ * Constructs a new DynamicFieldSerializer with the specified field selector holder.
+ *
+ * @param holder the field selector holder that provides the selector for filtering fields during serialization
+ */
public DynamicFieldSerializer(FieldSelectorHolder holder) {
this.holder = holder;
}
- @Override
- public Class handledType() {
- return Object.class;
- }
-
+ /**
+ * Serializes the given object value to JSON using the field selector from the holder.
+ * This method delegates to {@link #serializeWithSelector(Object, JsonGenerator, SerializerProvider, FieldSelector)}
+ * with the selector obtained from the holder.
+ *
+ * @param value the object to serialize
+ * @param gen the JSON generator used for writing JSON content
+ * @param provider the serializer provider for accessing serializers
+ * @throws IOException if an I/O error occurs during serialization
+ */
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider)
throws IOException {
serializeWithSelector(value, gen, provider, holder.getSelector());
}
+ /**
+ * Serializes the given object value to JSON based on the provided field selector.
+ *
+ * This method performs selective serialization by including only the fields specified in the selector.
+ * If the selector includes all fields, the default serialization is performed. Otherwise, it introspects
+ * the object's bean properties and serializes only those included in the selector. Nested field selectors
+ * are applied recursively for complex object structures.
+ *
+ *
+ * @param value the object to serialize, it may be null
+ * @param gen the JSON generator used for writing JSON content
+ * @param provider the serializer provider for accessing serializers and configuration
+ * @param selector the field selector that determines which fields to include in serialization
+ * @throws IOException if an I/O error occurs during serialization
+ */
public void serializeWithSelector(Object value, JsonGenerator gen,
SerializerProvider provider, FieldSelector selector) throws IOException {
@@ -46,8 +106,11 @@ public void serializeWithSelector(Object value, JsonGenerator gen,
gen.writeStartObject();
for (BeanPropertyDefinition prop : desc.findProperties()) {
+
String name = prop.getName();
- if (!selector.includes(name)) continue;
+ if (!selector.includes(name)) {
+ continue;
+ }
Object propValue = prop.getAccessor().getValue(value);
gen.writeFieldName(name);
diff --git a/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelector.java b/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelector.java
index 39225e36289..0d6cd7ffd1f 100644
--- a/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelector.java
+++ b/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelector.java
@@ -5,19 +5,83 @@
import java.util.Map;
import java.util.Set;
+/**
+ * A utility class for parsing and managing field selection specifications in JSON serialization.
+ *
+ * This class enables selective field inclusion during serialization by parsing a field specification
+ * string that supports both simple field names and nested field selections using parentheses notation.
+ *
Deep nesting: {@code "field1(nested1(deepNested1,deepNested2))"}
+ *
+ *
+ *
+ * When no specification is provided (null or blank), the selector allows all fields (unrestricted mode).
+ *
+ *
+ * @see LocalizedEventOutcomeSerializer
+ * @see DynamicFieldSerializer
+ * @see FieldSelectorHolder
+ */
+
public final class FieldSelector {
+ /**
+ * Set of field names to include at the current level of serialization.
+ * When null, all fields are included (unrestricted mode).
+ */
private final Set fields;
+
+ /**
+ * Map of field names to their corresponding nested {@link FieldSelector} instances.
+ * Enables hierarchical field selection for complex object structures.
+ * When null, no nested field restrictions are applied.
+ */
private final Map nested;
+ /**
+ * Creates a new FieldSelector in unrestricted mode.
+ *
+ * This constructor creates a selector that allows all fields to be included
+ * during serialization without any restrictions.
+ *
+ */
private FieldSelector() {
this(null, null);
}
+ /**
+ * Creates a new FieldSelector with specified field selections and nested selectors.
+ *
+ * @param fields the set of field names to include at this level, or null for unrestricted mode
+ * @param nested the map of field names to their nested selectors, or null if no nested selections
+ */
private FieldSelector(Set fields, Map nested) {
this.fields = fields;
this.nested = nested;
}
+ /**
+ * Parses a field specification string and creates a corresponding FieldSelector.
+ *
+ * The parser supports:
+ *
+ *
Comma-separated field names: {@code "field1,field2,field3"}
+ *
Nested field selections using parentheses: {@code "field1(nested1,nested2)"}
+ *
Multiple levels of nesting: {@code "field1(nested1(deepNested1))"}
+ *
+ *
+ *
+ * If the specification is null or blank, an unrestricted selector is returned that allows all fields.
+ *
+ *
+ * @param spec the field specification string to parse, may be null or blank
+ * @return a FieldSelector instance representing the parsed specification
+ * @throws IllegalArgumentException if the specification contains unmatched parentheses
+ */
public static FieldSelector parse(String spec) {
Set fields = new HashSet<>();
Map nested = new HashMap<>();
@@ -29,14 +93,14 @@ public static FieldSelector parse(String spec) {
int i = 0;
while (i < spec.length()) {
int commaIdx = nextCommaOrEnd(spec, i);
- int parenIdx = spec.indexOf('(', i);
+ int parenthesisIdx = spec.indexOf('(', i);
- if (parenIdx != -1 && parenIdx < commaIdx) {
- String name = spec.substring(i, parenIdx);
- int closeParen = findMatchingParen(spec, parenIdx);
- String inner = spec.substring(parenIdx + 1, closeParen);
+ if (parenthesisIdx != -1 && parenthesisIdx < commaIdx) {
+ String name = spec.substring(i, parenthesisIdx);
+ int closeParenthesisIdx = findMatchingParen(spec, parenthesisIdx);
+ String inner = spec.substring(parenthesisIdx + 1, closeParenthesisIdx);
nested.put(name, parse(inner));
- i = closeParen + 1;
+ i = closeParenthesisIdx + 1;
if (i < spec.length() && spec.charAt(i) == ',') i++;
} else {
fields.add(spec.substring(i, commaIdx));
@@ -46,16 +110,49 @@ public static FieldSelector parse(String spec) {
return new FieldSelector(fields, nested);
}
+ /**
+ * Checks whether the specified field should be included in serialization.
+ *
+ * A field is included if:
+ *
+ *
The selector is in unrestricted mode (fields is null), or
+ *
The field is explicitly listed in the fields set, or
+ *
The field has a nested selector defined
+ *
+ *
+ *
+ * @param field the name of the field to check
+ * @return true if the field should be included, false otherwise
+ */
public boolean includes(String field) {
if (fields == null) return true;
if (fields.contains(field)) return true;
return nested != null && nested.containsKey(field);
}
+ /**
+ * Checks whether this selector is in unrestricted mode, allowing all fields.
+ *
+ * Unrestricted mode occurs when no field specification was provided during parsing
+ * (i.e., the specification was null or blank).
+ *
+ *
+ * @return true if all fields should be included without restrictions, false otherwise
+ */
public boolean includeAll() {
return fields == null;
}
+ /**
+ * Retrieves the nested FieldSelector for the specified field.
+ *
+ * If no nested selector is defined for the field, returns an unrestricted selector
+ * that allows all fields at the nested level.
+ *
+ *
+ * @param field the name of the field whose nested selector to retrieve
+ * @return the nested FieldSelector for the field, or an unrestricted selector if none exists
+ */
public FieldSelector nested(String field) {
if (nested == null || !nested.containsKey(field)) {
return new FieldSelector(null, null); // no restriction on nested level either
@@ -63,6 +160,18 @@ public FieldSelector nested(String field) {
return nested.get(field);
}
+ /**
+ * Finds the index of the next comma at the current nesting depth, or the end of the string.
+ *
+ * This method tracks parenthesis depth to avoid splitting on commas that are inside
+ * nested field specifications. Only commas at depth 0 (not inside any parentheses)
+ * are considered as field separators.
+ *
+ *
+ * @param spec the specification string to search
+ * @param from the starting index for the search
+ * @return the index of the next comma at depth 0, or the length of the string if none found
+ */
private static int nextCommaOrEnd(String spec, int from) {
int depth = 0;
for (int i = from; i < spec.length(); i++) {
@@ -74,6 +183,18 @@ private static int nextCommaOrEnd(String spec, int from) {
return spec.length();
}
+ /**
+ * Finds the index of the closing parenthesis that matches the opening parenthesis at the specified position.
+ *
+ * This method correctly handles nested parentheses by tracking the depth level and returning
+ * the index of the closing parenthesis that brings the depth back to 0.
+ *
+ *
+ * @param spec the specification string to search
+ * @param openIdx the index of the opening parenthesis
+ * @return the index of the matching closing parenthesis
+ * @throws IllegalArgumentException if no matching closing parenthesis is found
+ */
private static int findMatchingParen(String spec, int openIdx) {
int depth = 0;
for (int i = openIdx; i < spec.length(); i++) {
diff --git a/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelectorHolder.java b/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelectorHolder.java
index be8015ff91a..fd21df71241 100644
--- a/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelectorHolder.java
+++ b/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelectorHolder.java
@@ -5,10 +5,32 @@
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;
+/**
+ * Request-scoped holder component for managing {@link FieldSelector} instances during HTTP request processing.
+ *
+ * This component is used in conjunction with {@link FieldSelectorInterceptor} to parse and store field selection
+ * criteria from HTTP request parameters (typically the "fields" query parameter). The held {@link FieldSelector}
+ * is then used by custom serializers like {@link LocalizedEventOutcomeSerializer} to control which fields
+ * are included in JSON response bodies.
+ *
+ *
+ * Being request-scoped ensures that each HTTP request has its own isolated instance of this holder,
+ * preventing thread-safety issues in concurrent request processing.
+ *
+ *
+ * @see FieldSelector
+ * @see FieldSelectorInterceptor
+ * @see LocalizedEventOutcomeSerializer
+ */
@Setter
@Getter
@Component
@RequestScope
public class FieldSelectorHolder {
+
+ /**
+ * The field selector that determines which fields should be included during serialization.
+ * Initialized with a default selector that includes all fields (parsed from null).
+ */
private FieldSelector selector = FieldSelector.parse(null);
}
diff --git a/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelectorInterceptor.java b/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelectorInterceptor.java
index afb1aced8a2..e3e53292f2d 100644
--- a/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelectorInterceptor.java
+++ b/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelectorInterceptor.java
@@ -16,8 +16,7 @@ public FieldSelectorInterceptor(FieldSelectorHolder holder) {
}
@Override
- public boolean preHandle(HttpServletRequest request, @NonNull HttpServletResponse response,
- @NonNull Object handler) {
+ public boolean preHandle(HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) {
String fields = request.getParameter("fields");
holder.setSelector(FieldSelector.parse(fields));
return true;
diff --git a/application-engine/src/main/java/com/netgrif/application/engine/serialization/LocalizedEventOutcomeSerializer.java b/application-engine/src/main/java/com/netgrif/application/engine/serialization/LocalizedEventOutcomeSerializer.java
index ab8bb93cb3d..26e511f04b1 100644
--- a/application-engine/src/main/java/com/netgrif/application/engine/serialization/LocalizedEventOutcomeSerializer.java
+++ b/application-engine/src/main/java/com/netgrif/application/engine/serialization/LocalizedEventOutcomeSerializer.java
@@ -13,16 +13,64 @@
import java.io.IOException;
+/**
+ * Custom JSON serializer for {@link LocalisedEventOutcome} objects that provides selective field serialization
+ * based on a {@link FieldSelector} configuration.
+ *
+ * This serializer handles various types of localized event outcomes including:
+ *
+ *
{@link LocalisedPetriNetEventOutcome} - outcomes related to Petri nets
+ *
{@link LocalisedCaseEventOutcome} - outcomes related to cases
+ *
{@link LocalisedTaskEventOutcome} - outcomes related to tasks
+ *
{@link LocalisedGetDataEventOutcome} - outcomes for data retrieval operations
+ *
{@link LocalisedGetDataGroupsEventOutcome} - outcomes for data groups retrieval
+ *
{@link LocalisedSetDataEventOutcome} - outcomes for data modification operations
+ *
+ * The serializer uses a {@link DynamicFieldSerializer} to handle nested object serialization with field selection support.
+ *
+ *
+ * @see LocalisedEventOutcome
+ * @see FieldSelector
+ * @see DynamicFieldSerializer
+ */
public class LocalizedEventOutcomeSerializer extends JsonSerializer {
+ /**
+ * Holder containing the {@link FieldSelector} that determines which fields should be included
+ * in the serialized JSON output.
+ */
private final FieldSelectorHolder selectorHolder;
+
+ /**
+ * Serializer used for dynamic field serialization of nested objects with field selection support.
+ */
private final DynamicFieldSerializer dynamicSerializer;
+ /**
+ * Constructs a new LocalizedEventOutcomeSerializer with the specified field selector holder.
+ *
+ * @param selectorHolder the holder containing the field selector configuration for controlling
+ * which fields are included in the serialized output
+ */
public LocalizedEventOutcomeSerializer(FieldSelectorHolder selectorHolder) {
this.selectorHolder = selectorHolder;
this.dynamicSerializer = new DynamicFieldSerializer(selectorHolder);
}
+ /**
+ * Serializes a {@link LocalisedEventOutcome} object to JSON format with selective field inclusion
+ * based on the configured {@link FieldSelector}.
+ *
+ * The method handles serialization of common fields (message, frontActions, outcomes) and type-specific
+ * fields based on the actual runtime type of the outcome object. Nested objects are serialized using
+ * the {@link DynamicFieldSerializer} with their corresponding nested field selectors.
+ *
+ *
+ * @param outcome the localized event outcome object to serialize
+ * @param gen the JSON generator used to write JSON content
+ * @param provider the serializer provider for accessing additional serializers
+ * @throws IOException if an I/O error occurs during serialization
+ */
@Override
public void serialize(LocalisedEventOutcome outcome, JsonGenerator gen, SerializerProvider provider)
throws IOException {
From 88a71a88756561a1fcd7ebeca97c1bae4b3e86e9 Mon Sep 17 00:00:00 2001
From: renczesstefan
Date: Tue, 16 Jun 2026 12:12:26 +0200
Subject: [PATCH 5/6] Improve robustness of `FieldSelector` parsing
Enhanced handling of blank or null specifications, added trimming for field names, and ensured empty names are excluded during parsing.
---
.../engine/serialization/FieldSelector.java | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelector.java b/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelector.java
index 0d6cd7ffd1f..d084f5fad99 100644
--- a/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelector.java
+++ b/application-engine/src/main/java/com/netgrif/application/engine/serialization/FieldSelector.java
@@ -83,27 +83,29 @@ private FieldSelector(Set fields, Map nested) {
* @throws IllegalArgumentException if the specification contains unmatched parentheses
*/
public static FieldSelector parse(String spec) {
- Set fields = new HashSet<>();
- Map nested = new HashMap<>();
-
if (spec == null || spec.isBlank()) {
- return new FieldSelector();
+ return new FieldSelector(null, null);
}
+ Set fields = new HashSet<>();
+ Map nested = new HashMap<>();
+
int i = 0;
while (i < spec.length()) {
int commaIdx = nextCommaOrEnd(spec, i);
int parenthesisIdx = spec.indexOf('(', i);
if (parenthesisIdx != -1 && parenthesisIdx < commaIdx) {
- String name = spec.substring(i, parenthesisIdx);
+ String name = spec.substring(i, parenthesisIdx).trim();
int closeParenthesisIdx = findMatchingParen(spec, parenthesisIdx);
String inner = spec.substring(parenthesisIdx + 1, closeParenthesisIdx);
+ fields.add(name);
nested.put(name, parse(inner));
i = closeParenthesisIdx + 1;
if (i < spec.length() && spec.charAt(i) == ',') i++;
} else {
- fields.add(spec.substring(i, commaIdx));
+ String name = spec.substring(i, commaIdx).trim();
+ if (!name.isEmpty()) fields.add(name);
i = commaIdx + 1;
}
}
From b68cae7b017da8297ed7e4d409dbe3ec79956686 Mon Sep 17 00:00:00 2001
From: renczesstefan
Date: Mon, 6 Jul 2026 12:38:54 +0200
Subject: [PATCH 6/6] [NAE-2451] Optimize and Reduce Outcome Size
- Refactor serialization components to replace `JsonSerializer` with `ValueSerializer` and update `ObjectMapper` configuration for improved compatibility.
---
.../serialization/DynamicFieldSerializer.java | 32 ++++++-------
.../LocalizedEventOutcomeSerializer.java | 45 ++++++++++---------
.../ObjectMapperConfiguration.java | 12 +++--
3 files changed, 47 insertions(+), 42 deletions(-)
diff --git a/application-engine/src/main/java/com/netgrif/application/engine/serialization/DynamicFieldSerializer.java b/application-engine/src/main/java/com/netgrif/application/engine/serialization/DynamicFieldSerializer.java
index e48fa9de5d3..caf502df6e9 100644
--- a/application-engine/src/main/java/com/netgrif/application/engine/serialization/DynamicFieldSerializer.java
+++ b/application-engine/src/main/java/com/netgrif/application/engine/serialization/DynamicFieldSerializer.java
@@ -1,11 +1,13 @@
package com.netgrif.application.engine.serialization;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.BeanDescription;
-import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
+import tools.jackson.core.JsonGenerator;
+import tools.jackson.databind.BeanDescription;
+import tools.jackson.databind.JavaType;
+import tools.jackson.databind.SerializationContext;
+import tools.jackson.databind.ValueSerializer;
+import tools.jackson.databind.introspect.BeanPropertyDefinition;
import java.io.IOException;
@@ -41,7 +43,7 @@
* @see FieldSelector
* @see FieldSelectorHolder
*/
-public class DynamicFieldSerializer extends JsonSerializer {
+public class DynamicFieldSerializer extends ValueSerializer {
/**
* Holder containing the field selector used to determine which fields should be serialized.
@@ -68,9 +70,8 @@ public DynamicFieldSerializer(FieldSelectorHolder holder) {
* @throws IOException if an I/O error occurs during serialization
*/
@Override
- public void serialize(Object value, JsonGenerator gen, SerializerProvider provider)
- throws IOException {
- serializeWithSelector(value, gen, provider, holder.getSelector());
+ public void serialize(Object value, JsonGenerator gen, SerializationContext context) {
+ serializeWithSelector(value, gen, context, holder.getSelector());
}
/**
@@ -88,8 +89,7 @@ public void serialize(Object value, JsonGenerator gen, SerializerProvider provid
* @param selector the field selector that determines which fields to include in serialization
* @throws IOException if an I/O error occurs during serialization
*/
- public void serializeWithSelector(Object value, JsonGenerator gen,
- SerializerProvider provider, FieldSelector selector) throws IOException {
+ public void serializeWithSelector(Object value, JsonGenerator gen, SerializationContext context, FieldSelector selector) {
if (value == null) {
gen.writeNull();
@@ -97,12 +97,12 @@ public void serializeWithSelector(Object value, JsonGenerator gen,
}
if (selector.includeAll()) {
- provider.defaultSerializeValue(value, gen);
+ context.findValueSerializer(value.getClass()).serialize(value, gen, context);
return;
}
- JavaType type = provider.constructType(value.getClass());
- BeanDescription desc = provider.getConfig().introspect(type);
+ JavaType type = context.constructType(value.getClass());
+ BeanDescription desc = context.introspectBeanDescription(type);
gen.writeStartObject();
for (BeanPropertyDefinition prop : desc.findProperties()) {
@@ -113,13 +113,13 @@ public void serializeWithSelector(Object value, JsonGenerator gen,
}
Object propValue = prop.getAccessor().getValue(value);
- gen.writeFieldName(name);
+ gen.writeName(name);
FieldSelector nested = selector.nested(name);
if (nested.includeAll()) {
- provider.defaultSerializeValue(propValue, gen);
+ context.findValueSerializer(propValue.getClass()).serialize(propValue, gen, context);
} else {
- serializeWithSelector(propValue, gen, provider, nested);
+ serializeWithSelector(propValue, gen, context, nested);
}
}
gen.writeEndObject();
diff --git a/application-engine/src/main/java/com/netgrif/application/engine/serialization/LocalizedEventOutcomeSerializer.java b/application-engine/src/main/java/com/netgrif/application/engine/serialization/LocalizedEventOutcomeSerializer.java
index 26e511f04b1..4f544a24c63 100644
--- a/application-engine/src/main/java/com/netgrif/application/engine/serialization/LocalizedEventOutcomeSerializer.java
+++ b/application-engine/src/main/java/com/netgrif/application/engine/serialization/LocalizedEventOutcomeSerializer.java
@@ -1,8 +1,5 @@
package com.netgrif.application.engine.serialization;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.SerializerProvider;
import com.netgrif.application.engine.workflow.web.responsebodies.eventoutcomes.LocalisedGetDataEventOutcome;
import com.netgrif.application.engine.workflow.web.responsebodies.eventoutcomes.LocalisedGetDataGroupsEventOutcome;
import com.netgrif.application.engine.workflow.web.responsebodies.eventoutcomes.LocalisedSetDataEventOutcome;
@@ -10,6 +7,10 @@
import com.netgrif.application.engine.workflow.web.responsebodies.eventoutcomes.base.LocalisedEventOutcome;
import com.netgrif.application.engine.workflow.web.responsebodies.eventoutcomes.base.LocalisedPetriNetEventOutcome;
import com.netgrif.application.engine.workflow.web.responsebodies.eventoutcomes.base.LocalisedTaskEventOutcome;
+import org.springframework.boot.jackson.JacksonComponent;
+import tools.jackson.core.JsonGenerator;
+import tools.jackson.databind.SerializationContext;
+import tools.jackson.databind.ValueSerializer;
import java.io.IOException;
@@ -33,7 +34,8 @@
* @see FieldSelector
* @see DynamicFieldSerializer
*/
-public class LocalizedEventOutcomeSerializer extends JsonSerializer {
+@JacksonComponent(type = LocalisedEventOutcome.class)
+public class LocalizedEventOutcomeSerializer extends ValueSerializer {
/**
* Holder containing the {@link FieldSelector} that determines which fields should be included
@@ -72,48 +74,47 @@ public LocalizedEventOutcomeSerializer(FieldSelectorHolder selectorHolder) {
* @throws IOException if an I/O error occurs during serialization
*/
@Override
- public void serialize(LocalisedEventOutcome outcome, JsonGenerator gen, SerializerProvider provider)
- throws IOException {
+ public void serialize(LocalisedEventOutcome outcome, JsonGenerator gen, SerializationContext context) {
gen.writeStartObject();
FieldSelector selector = selectorHolder.getSelector();
if (selector.includes("message") && outcome.getMessage() != null) {
- gen.writeObjectField("message", outcome.getMessage());
+ gen.writePOJOProperty("message", outcome.getMessage());
}
if (selector.includes("frontActions") && outcome.getFrontActions() != null) {
- gen.writeObjectField("frontActions", outcome.getFrontActions());
+ gen.writePOJOProperty("frontActions", outcome.getFrontActions());
}
if (selector.includes("outcomes")
&& outcome.getOutcomes() != null) {
- gen.writeArrayFieldStart("outcomes");
+ gen.writeArrayPropertyStart("outcomes");
for (LocalisedEventOutcome child : outcome.getOutcomes()) {
- provider.defaultSerializeValue(child, gen);
+ context.findValueSerializer(child.getClass()).serialize(child, gen, context);
}
gen.writeEndArray();
}
if (outcome instanceof LocalisedPetriNetEventOutcome specificOutcome && selector.includes("net") && specificOutcome.getNet() != null) {
- gen.writeFieldName("net");
- dynamicSerializer.serializeWithSelector(specificOutcome.getNet(), gen, provider, selector.nested("net"));
+ gen.writeName("net");
+ dynamicSerializer.serializeWithSelector(specificOutcome.getNet(), gen, context, selector.nested("net"));
}
if (outcome instanceof LocalisedCaseEventOutcome specificOutcome && selector.includes("case") && specificOutcome.getaCase() != null) {
- gen.writeFieldName("aCase");
- dynamicSerializer.serializeWithSelector(specificOutcome.getaCase(), gen, provider, selector.nested("case"));
+ gen.writeName("aCase");
+ dynamicSerializer.serializeWithSelector(specificOutcome.getaCase(), gen, context, selector.nested("case"));
}
if (outcome instanceof LocalisedTaskEventOutcome specificOutcome && selector.includes("task") && specificOutcome.getTask() != null) {
- gen.writeFieldName("task");
- dynamicSerializer.serializeWithSelector(specificOutcome.getTask(), gen, provider, selector.nested("task"));
+ gen.writeName("task");
+ dynamicSerializer.serializeWithSelector(specificOutcome.getTask(), gen, context, selector.nested("task"));
}
if (outcome instanceof LocalisedGetDataEventOutcome specificOutcome && selector.includes("data") && specificOutcome.getData() != null) {
- gen.writeFieldName("data");
- dynamicSerializer.serializeWithSelector(specificOutcome.getData(), gen, provider, selector.nested("data"));
+ gen.writeName("data");
+ dynamicSerializer.serializeWithSelector(specificOutcome.getData(), gen, context, selector.nested("data"));
}
if (outcome instanceof LocalisedGetDataGroupsEventOutcome specificOutcome && selector.includes("data") && specificOutcome.getData() != null) {
- gen.writeFieldName("data");
- dynamicSerializer.serializeWithSelector(specificOutcome.getData(), gen, provider, selector.nested("data"));
+ gen.writeName("data");
+ dynamicSerializer.serializeWithSelector(specificOutcome.getData(), gen, context, selector.nested("data"));
}
if (outcome instanceof LocalisedSetDataEventOutcome specificOutcome && selector.includes("changedFields") && specificOutcome.getChangedFields() != null) {
- gen.writeFieldName("changedFields");
- dynamicSerializer.serializeWithSelector(specificOutcome.getChangedFields(), gen, provider, selector.nested("changedFields"));
+ gen.writeName("changedFields");
+ dynamicSerializer.serializeWithSelector(specificOutcome.getChangedFields(), gen, context, selector.nested("changedFields"));
}
gen.writeEndObject();
diff --git a/application-engine/src/main/java/com/netgrif/application/engine/serialization/ObjectMapperConfiguration.java b/application-engine/src/main/java/com/netgrif/application/engine/serialization/ObjectMapperConfiguration.java
index d6f16c23c20..f311a8205c1 100644
--- a/application-engine/src/main/java/com/netgrif/application/engine/serialization/ObjectMapperConfiguration.java
+++ b/application-engine/src/main/java/com/netgrif/application/engine/serialization/ObjectMapperConfiguration.java
@@ -2,16 +2,20 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.netgrif.application.engine.workflow.web.responsebodies.eventoutcomes.base.LocalisedEventOutcome;
-import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import tools.jackson.databind.module.SimpleModule;
@Configuration
public class ObjectMapperConfiguration {
@Bean
- public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer(FieldSelectorHolder holder) {
- return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL)
- .serializerByType(LocalisedEventOutcome.class, new LocalizedEventOutcomeSerializer(holder));
+ public JsonMapperBuilderCustomizer jsonCustomizer(FieldSelectorHolder holder) {
+ SimpleModule module = new SimpleModule();
+ module.addSerializer(LocalisedEventOutcome.class, new LocalizedEventOutcomeSerializer(holder));
+ return builder -> builder
+ .changeDefaultPropertyInclusion(include -> include.withValueInclusion(JsonInclude.Include.NON_NULL))
+ .findAndAddModules();
}
}