I am doing quite similar stuff at my current day job 👍🏻

Hope My suggestions can help.


1# “NO” to using a custom de/serializer. 
 I started using @JsonTypeInfo at work to avoid exactly that. 
 Having to write custom de/serializers for every DTO class.

2# Use Id.Name instead.

 I suggest to change DEDUCTION based handling on REST layer to 
JsonTypeInfo.Id.NAME <http://jsontypeinfo.id.name/> based. 

 This will require change in REST API specification, but in the long term 
it will be easier to debug/maintain.

 Imagine how much a troublesome it would be for a server to having to  
“assume” every time what the client intends to do with the request!


3# Maintain `@JsonSubTypes.Type.name` attribute as constants.

 Simple coding convention, maintain a variable in one place.

 Since @JsonTypeInfo provides polymorphic type handling which is already 
complex, hard-coding type id will get back to you soon. It took me only a 
few days … :(

 Take below code for example

# AS-IS

```java
@JsonSubTypes({

        @JsonSubTypes.Type(value = AndDbDto.class, name = AND_VALUE),

        @JsonSubTypes.Type(value = OrDbDto.class, name = OR_VALUE)

})

```

# TO-BE

```java
@JsonSubTypes({

        @JsonSubTypes.Type(value = AndDbDto.class, name = AND_VALUE),

        @JsonSubTypes.Type(value = OrDbDto.class, name = OR_VALUE),

        @JsonSubTypes.Type(value = ConditionDbDto.class, name = 
CONDITION_VALUE)

})

public enum DbExpressions {

      AND, OR, CONITION

     // Constants

     public static final String AND_VALUE = “and”;

     public static final String OR_VALUE = “or”;

      public static final String CONDITION_VALUE = “condition”;

}
```
On Thursday, May 4, 2023 at 12:51:30 PM UTC+9 Tatu Saloranta wrote:

> On Mon, May 1, 2023 at 4:11 PM Marcus Biel <indu...@gmail.com> wrote:
> >
> > 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.
>
> While I haven't built anything quite like this myself, I have seen
> similar use cases, for what it is worth.
> So maybe others with direct experience can share their learnings.
>
> >
> > 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.
>
> Yes, that sounds like a complex beast.
>
> > Here are the two code snippets for the REST DTOs and the ORM Mapper:
> >
> > REST DTO sample:
> >
> > @JsonTypeInfo(use = DEDUCTION)
> > @JsonSubTypes({
> > @Type(AndDto.class),
> > @Type(OrDto.class),
> > @Type(ConditionDto.class),
> > @Type(FieldDto.class),
> > @Type(LabelDto.class)
> > })
> > public interface ExpressionDto {
> > }
> >
> > ORM layer DTO sample of basically the same interface:
> > @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? I'm not sure, and I'm open to 
> suggestions. Currently, the project is using the latest versions of Java 
> and Frameworks - Java 20, Hibernate 6.2, and Quarkus 3.x. I could leverage 
> Sealed classes if Jackson supports them.
>
> Custom deserializers can be tricky: obviously you can do anything and
> everything, but at the same time if they need to interoperate with
> standard Jackson (de)serializers there's quite a bit more work to do.
>
> Another approach that can be helpful is 2-pass (or multi-pass), in
> which a JsonNode-based model is bound from/to JSON, modified, then
> used as source for ObjectMapper. This can be used for all kinds of
> pre-/post-processing.
>
> >
> > Also, could someone clarify the difference between the use of DEDUCTION 
> in the REST layer and JsonTypeInfo.Id.NAME in the database layer version 
> of the same class?
>
> Ok, so: DEDUCTION basically means that no explicit Type Id (property,
> or wrapper Object/Array) is used; type is deduced solely from the
> existence of specific property names. Value types then must have,
> each, at least one unique property name (something no other type has).
> On serialization no type id is written, only regular properties.
>
> The other choice used is to add (and use) specific Object Property
> (here "type") to contain Type Id; and as id use logical, annotated
> "name" (instead of Java class, the main alternative).
> Type Id is written as Object metadata in addition to regular
> properties (or in general, regular value representation).
>
> I must say I am not sure why DEDUCTION was used here: I think it's
> more common to use explicit Type Ids for both.
>
> -+ Tatu +-
>
> >
> > Thanks a lot in advance!
> >
> > Marcus
> >
> > --
> > 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 jackson-user...@googlegroups.com.
> > To view this discussion on the web visit 
> https://groups.google.com/d/msgid/jackson-user/14120539-f3f0-4458-b206-c2b31002a9e2n%40googlegroups.com
> .
>

-- 
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 jackson-user+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jackson-user/002717d4-eb31-4ac1-90cc-b03f42fdddffn%40googlegroups.com.

Reply via email to