Hello everyone,

I'm dealing with a project that has a complex setup, and I'm trying to 
simplify it. Our application allows users to establish Conditions or 
Filters in the UI. These Conditions/Filters are stored in a database and 
can be used to limit database queries using WHERE conditions. 
Interestingly, these filters can be built recursively from other filters.

Our current structure involves DTO classes marked with Jackson annotations, 
which build a hierarchy. This hierarchy is mapped into business objects, 
despite not having real business logic. These are later converted into 
database DTOs. The system is quite intricate as it spans across three 
layers - REST, Domain, and ORM Mapper. Additionally, the code, written two 
years ago by another developer, extensively uses Jackson Annotations, which 
increases the complexity and makes it difficult for me to understand.

Here are the two code snippets for the REST DTOs and the ORM Mapper:

REST DTOs:

java

@JsonTypeInfo(use = DEDUCTION) // No idea why DEDUCTION was used here but 
JsonTypeInfo.Id.NAME, below...
@JsonSubTypes({
        @Type(AndDto.class),
        @Type(OrDto.class),
        @Type(ConditionDto.class),
        @Type(FieldDto.class),
        @Type(LabelDto.class)
})
public interface ExpressionDto {
}

ORM Mapper:

java

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        property = "type")
@JsonSubTypes({
        @JsonSubTypes.Type(value = AndDbDto.class, name = "and"),
        @JsonSubTypes.Type(value = OrDbDto.class, name = "or"),
        @JsonSubTypes.Type(value = ConditionDbDto.class, name = 
"condition"),
        @JsonSubTypes.Type(value = FieldDbDto.class, name = "field"),
        @JsonSubTypes.Type(value = LabelDBDto.class, name = "label")
})
public interface ExpressionDbData {
}

I'm faced with the task of integrating about 15 more logical operators into 
the model, on top of the two already present - Equals for Field and 
Contains for Labels. Incorporating these operators would significantly ramp 
up the complexity of the existing model.

Each field type is linked to a data type - Text, Number, or Date. Each data 
type should support its specific logical comparison operators:

    TEXT: EQUAL, EQUAL_IGNORE_CASE, NOT_EQUAL, START_WITH, ENDS_WITH, 
CONTAINS
    NUMBER: EQUAL, NOT_EQUAL, GREATER, SMALLER, GREAT_EQUAL, SMALLER_EQUAL
    DATE: EQUAL, BEFORE, AFTER, BEFORE_OR_EQUAL, EQUAL_OR_AFTER

I'm searching for a more straightforward yet valid method to accept these 
conditions/filters from the frontend, store them in the database, and later 
apply them to database queries. At present, we're achieving this with a 
custom JPA CriteriaBuilder.

Could using a custom Serializer / Deserializer or maybe an 
AttributeConverter be helpful in this case?
Something like this maybe:
    @Override
    public void serialize(AndExpression value, JsonGenerator gen, 
SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        gen.writeStringField("type", "and");
        gen.writeFieldName("expressions");
        gen.writeStartArray();
        for (Expression expression : value.getExpressions()) {
            gen.writeObject(expression);
        }
        gen.writeEndArray();
        gen.writeEndObject();
    }
}

public class AndExpressionDeserializer extends 
StdDeserializer<AndExpression> {
    public AndExpressionDeserializer() {
        super(AndExpression.class);
    }

    @Override
    public AndExpression deserialize(JsonParser p, DeserializationContext 
ctxt) throws IOException, JsonProcessingException {
        JsonNode node = p.getCodec().readTree(p);
        JsonNode expressionsNode = node.get("expressions");
        List<Expression> expressions = new ArrayList<>();
        for (JsonNode expressionNode : expressionsNode) {
            Expression expression = 
p.getCodec().treeToValue(expressionNode, Expression.class);
            expressions.add(expression);
        }
        return new AndExpression(expressions);
    }
}

I'm not sure, and I'm open to suggestions. Currently, I'm using the latest 
versions of Java and Frameworks - Java 20, Hibernate 6.2, and Quarkus 3.x,
so, for instance, I could use Sealed classes if it would help...

Thanks in advance,


Marcus
p.s.: Posted this again as my earlier message did not appear. Excuse me if 
this appears as a duplicate. 

-- 
You received this message because you are subscribed to the Google Groups 
"jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jackson-user/911c4011-02ee-477e-8967-9dbbc0043ef1n%40googlegroups.com.

Reply via email to