Package io.github.og4dev.annotation
This package provides annotations that enable fine-grained control over JSON string field processing in the OG4Dev Spring API Response library. Unlike automatic processing approaches, these annotations follow an opt-in philosophy: fields are preserved as-is by default, and you explicitly choose which fields should be trimmed or validated.
Philosophy: Opt-in by Default
Version 1.3.0 introduces an opt-in security model that gives developers complete control:
- Default Behavior: String fields are preserved exactly as received (no modifications)
- Explicit Control: Use annotations to enable trimming or XSS validation per field
- No Surprises: Your data is never modified unless you explicitly request it
- Production-Ready: Enable security features only where needed
Available Annotations:
AutoTrim- Opt-in automatic whitespace trimming for specific string fields (e.g., usernames, emails, search queries)XssCheck- Opt-in XSS validation with fail-fast HTML tag rejection (e.g., user comments, profile fields, user-generated content)
Default Behavior (No Annotations):
By default, string fields in DTOs are NOT modified during JSON deserialization:
- No Trimming: Leading and trailing whitespace is preserved
- No XSS Validation: HTML tags are allowed (not checked)
- Null Preservation: Null values remain null (not converted to empty strings)
public class DefaultDTO {
private String username; // Preserved as-is: " john " → " john "
private String comment; // Preserved as-is: "<b>Hi</b>" → "<b>Hi</b>"
}
Opt-in Features:
1. Automatic Trimming with @AutoTrim
Apply @AutoTrim to fields where you want to remove leading/trailing whitespace:
import io.github.og4dev.annotation.AutoTrim;
public class UserRegistrationDTO {
@AutoTrim
private String username; // Trimmed: " john " → "john"
@AutoTrim
private String email; // Trimmed: " [email protected] " → "[email protected]"
private String password; // NOT trimmed: " pass " → " pass "
}
2. XSS Validation with @XssCheck
Apply @XssCheck to fields where you want to reject HTML tags:
import io.github.og4dev.annotation.XssCheck;
public class CommentDTO {
@XssCheck
private String content; // Rejects: "<script>alert()</script>"
@XssCheck
private String authorName; // Rejects: "<b>John</b>"
private String commentId; // Allows: "<id-123>" (no validation)
}
3. Combining Both Annotations
Use both annotations together for fields that need trimming AND XSS validation:
import io.github.og4dev.annotation.AutoTrim;
import io.github.og4dev.annotation.XssCheck;
public class SecureInputDTO {
@AutoTrim
@XssCheck
private String username; // First trimmed, then XSS-validated
@XssCheck
private String comment; // Only XSS-validated (not trimmed)
@AutoTrim
private String email; // Only trimmed (not XSS-validated)
private String bio; // Neither (preserved as-is)
}
Processing Order:
When both annotations are present on a field, processing happens in this order:
- String is trimmed (if
@AutoTrimis present) - Trimmed string is checked for HTML tags (if
@XssCheckis present) - If HTML tags found, an exception is thrown
Migration from v1.2.0:
Version 1.2.0 automatically trimmed and validated all string fields. Version 1.3.0 requires explicit annotations. To maintain the same behavior:
// v1.2.0 (automatic)
public class UserDTO {
private String username; // Was automatically trimmed
}
// v1.3.0 (opt-in)
import io.github.og4dev.annotation.AutoTrim;
import io.github.og4dev.annotation.XssCheck;
public class UserDTO {
@AutoTrim
@XssCheck
private String username; // Now explicitly enabled
}
Integration with Jackson:
These annotations are processed by the AdvancedStringDeserializer registered in
ApiResponseAutoConfiguration.strictJsonCustomizer().
The deserializer uses Jackson's contextual deserialization mechanism
(ValueDeserializer.createContextual(tools.jackson.databind.DeserializationContext, tools.jackson.databind.BeanProperty)) to detect
annotations and create specialized deserializer instances with the appropriate behavior.
Performance:
The annotation detection and deserializer creation happens once per field during Jackson ObjectMapper initialization, not on every request. This ensures optimal runtime performance with negligible overhead (typically <1ms per request).
- Since:
- 1.3.0
- Version:
- 1.3.0
- Author:
- Pasindu OG
- See Also: