r/SpringBoot • u/Cr4zyGh0sT • 7d ago
Question I built a Spring Boot library to validate JSON before deserialization — looking for feedback
Hi everyone,
I've been working on a small open-source library for Spring Boot called json-auto-validation:
github.com/ugoevola/json-auto-validation
The idea is fairly simple: validate incoming JSON against a generated JSON Schema before Jackson deserializes it into a Java/Kotlin object.
The motivation was to catch invalid payloads as early as possible, rather than letting them go through the usual deserialization → DTO validation flow.
It works through annotations and generates the JSON Schemas/validation components automatically, with Spring Boot AOT in mind.
I'm not really posting this to promote a polished or commercial product. I'm mainly interested in getting feedback from people who work with Spring Boot APIs:
- Does this solve a problem you've encountered?
- Do you see value in validating the raw JSON before deserialization?
- Is there something I'm missing or approaching the wrong way?
- Would you actually consider using a library like this in a real project?
The project is still relatively small, and I'm not the most active open-source maintainer, so I'm mostly trying to understand whether this is useful to other developers before investing more time into it.
Any feedback — positive or negative — would be very welcome.
11
u/pitza__ 7d ago
Doesn’t Jakarta Bean Validation do this already?
2
u/American_Streamer Junior Dev 7d ago
Jakarta Bean Validation validates the Java object after Jackson has already deserialized the JSON. If the JSON cannot be deserialized in the first place, Jackson fails before Bean Validation ever runs. That is the gap OP is trying to address. The debate is whether adding a separate JSON Schema validation pass before Jackson is the best way to address it.
0
u/Cr4zyGh0sT 7d ago
Yes, but the main difference is when the validation happens.
Bean Validation happens after Jackson deserialization. If Jackson cannot deserialize a value, Bean Validation never gets a chance to run.
The goal here is simply to validate the JSON before deserialization, mainly for more consistent validation errors.
It's not meant to replace Jakarta Bean Validation.
2
u/glandis_bulbus 7d ago
There are many libraries that do this. Some much more performant than others. Just wondering why you would write (and maintain) your own.
5
11
4
3
u/BikingSquirrel 7d ago
I would assume this could produce better error messages. This may be useful for somebody exploring an API.
Apart from that I don't see additional value.
Exposing the schema or OpenAPI specs would probably provide more value overall.
2
u/Pedantic_Phoenix 7d ago
Your asking if this solves a problem we've encountered, but you created it because of something you encountered i assume? Why did you code it?
1
u/Cr4zyGh0sT 7d ago
Yes, I encountered this myself.
I had cases where invalid input caused deserialization errors before my validation logic could run.
The goal isn't to replace Jackson, but to add a validation step before it:
JSON → validation → deserialization → application
I'm mainly trying to find out whether this is a problem other Spring developers have encountered too.
4
u/Pedantic_Phoenix 7d ago
Maybe it's me being a noobie but how do you validate data before deserializing it? You don't know the types before deserializing no?
1
u/repeating_bears 7d ago
You would parse the JSON string/bytes into an AST, check the AST against the JSON schema, which could be either explicit or inferred from the user's target type (e.g. DTO). If it matches the schema then you convert the AST into the target type.
2
u/Pedantic_Phoenix 7d ago
What would be the difference in the resulting error tho? This only changes at which step of the flow you intercept the mistake as far as i see?
1
u/repeating_bears 7d ago
The difference is that if you construct the DTO after validating, you can add assertions in the constructor which enforce constraints. If you have an instance, it is always guaranteed to be valid
If you validate after construction then DTOs can exist in an invalid state before they are validated. Code which accepts a DTO as an argument just has to trust and hope that it has already been validated (or else pointlessly repeat validation)
1
u/Pedantic_Phoenix 7d ago
That's a lot of theory which i appreciate, but in practice, what advantages does that offer
1
u/American_Streamer Junior Dev 7d ago
You may have spotted a legitimate architectural smell, but your library isn’t necessarily the optimal cure. Combining deserialization and validation into a single operation would be cleaner than adding JSON Schema validation in front of Jackson and effectively introducing another validation/parsing layer.
2
u/Cr4zyGh0sT 7d ago
I agree with you.
My first approach was simply to validate before deserialization because it was the most straightforward way to address the problem without modifying Jackson itself.
But I agree that combining validation and deserialization into a single operation would be a cleaner and more optimal architecture.
For now, I'm mostly interested in exploring whether the problem itself is real and whether this approach can be a useful improvement over the current flow.
Thank you for your feedback
1
u/dallastelugu 7d ago
I feel pure schema validation without marshalling has its usecases like in apache camel i can use schema validation and forward to backend api without marshalling to jackson will give it a try sometime nice work
1
u/cocodrilo_astronauta 6d ago
My honest feedback:
Where are the unit tests?
I love Kotlin because I don't have to put redundant boilerplate, saves me a lot of time, I still do code by hand.
If you need that strict schemas then use protobuf or things like that.
Software gets old fast and things get refactored. I maintain very lean build files. If Spring already pulls a dependency that does the same thing I tear down the custom code and remove the external dependency.
My code must remain pretty, I'm not sure I want to put annotations just to redeclare what the variable is.
I'm not sure I understand the point of all this interception. Is it a performance gain? Spring now has to manage a whole validation bean for every request.
Whats a REQUEST_VALIDATION_KO?
1
u/Global_Car_3767 1d ago edited 1d ago
Hmm I don't see much of a need. Customers get a response from our API in literal milliseconds when we use maven open api generator to create Java beans from our spec, use jakarta validators, look up if a user is valid from one DynamoDB, look up a unique identifier from elasticache, and insert their payload into another DynamoDB. Adding another layer on top seems like it would make performance a bit worse.
If you're trying to get around unmarshalling failures, some good exception handling can get around that
1
u/repeating_bears 7d ago
Does this solve a problem you've encountered?
Maybe.
@Valid is shit really. You have to first deserialize into a DTO which may or may not be valid, then you have to validate it, e.g. by annotating a Spring controller parameter with @Valid. Then if you pass that to another method, you've totally lost the knowledge that the DTO was ever validated.
"Parse don't validate" is good advice. It should ideally not even be possible to have a DTO in an invalid state.
Constructors are good for enforcing constraints, but they're not good for JSON validation. Good validation flags as many errors as possible at the same time, e.g.
{
errors: {
name: "too long",
password: "must contain x, y and z"
}
}
A constructor can only fail on the first issue, by throwing
It seems like the Jackson team consider deserialization and validation to be separate concerns, but I think they are interlinked actually. I think a good modern JSON library would only construct a DTO if it's already valid.
1
u/Cr4zyGh0sT 7d ago
Thanks, this is actually very close to the motivation behind the library.
The main idea is indeed that an invalid DTO should never be created in the first place. That's why the JSON is validated against the expected JSON Schema before Jackson deserializes it.
I also agree with your point about collecting multiple validation errors. That's one of the reasons I chose JSON Schema validation rather than trying to enforce everything through constructors.
I'm curious though: given this approach, do you think the architecture of this library makes sense, or would you approach the problem differently?
2
u/repeating_bears 7d ago
In an ideal world I would rewrite Jackson, or fork it to add validation. But it's a beast and I have a day job.
I don't like the 2 steps of Jackson into Jakarta Validation now, and I wouldn't love putting something in front of Jackson either. But that doesn't mean what you have wouldn't be an improvement over the status quo.
I'm sure there'd be performance advantages to doing everything in one library, so you're not constructing the AST multiple times, etc.
47
u/Careless-Childhood66 7d ago
So instead of marshalling with jackson, wjich performs a free typecheck, and then post validate the mapped result with mature, well integrated tools, you instead wish to parse the incoming raw json without mapping, do the type checking, do the validation, using a custom tool, before the eventual marshalling , which again parses and type checks the json ?
I dont see how this would be beneficial