fluidsonic / fluid-json

A JSON library written in pure Kotlin
Apache License 2.0
31 stars 7 forks source link

Add support for Validation #31

Closed raderio closed 4 years ago

raderio commented 5 years ago

Usually on deserialization we want to collect all validation errors and return them in response to the client. In order to catch all error the validation should be done before object creation.

If it will be done after object creation, in init block, than validation will be separated in 2 phases, first one will be validation regarding non-nullable field, because we cannot create objects if they have non-nullable properties. The second one will be to do structural validation: min/max values, length, regexp pattern, etc.

Example class Data(val name: String, val age: Int, val email: String) when we send a json {"email": "xyz@xyz.com", "name": "A"} we should return a response where to indicate that age can not be null and name size must be greater than 2, at once to send all the errors.

Also, structural validation will be great to do based on annotations and not in init block, something like JSR 303. This will be useful for documentation generation, it is far easier to generate based on annotations.

How I see the flow:

  1. Read annotations and generate validation rules. Can be done by 3rd party library. As result Map<Class, List>
  2. Parse json as a map
  3. Apply validation rules. Validation rules can be passed as parameter in configuration.
  4. Create object
fluidsonic commented 5 years ago

Thank you @raderio for opening this discussion.

Here some questions and thoughts regarding your suggestion:

raderio commented 5 years ago

In the majority of scenarios clients send valid JSON

If you have only one version of API and only one client, than yes, but we have 3 clients(we, android, ios) and should support several version of each.

Take Twitter for example. There are complex rules involved to calculate how long a tweet actually is

This is more like an exception for rule, usually you have an input with max length

fluidsonic commented 5 years ago

In the majority of scenarios clients send valid JSON

If you have only one version of API and only one client, than yes, but we have 3 clients(we, android, ios) and should support several version of each.

How can validation which goes beyond structure help you in this situation? From the client's perspective there will be useful error messages in any case. Or is it about the documentation? I'm also used to having multiple clients each having widely different versions as typically happens as you release more and more app updates. I've stopped versioning APIs long time ago and instead implement capabilities. Each client tells in the request what API capabilities they support and the API server will adjust their functionality and response format accordingly to consider and/or compensate for missing capabilities.

Take Twitter for example. There are complex rules involved to calculate how long a tweet actually is

This is more like an exception for rule, usually you have an input with max length

It's a more extreme one, yes, but there are many more. In some cases the values may depend on the client, on the database or other external or complex information. My suggestion is instead of having part of the validation in the parsing or data layer and part of it in the business logic layer have all at one place so there is no guessing at runtime what data has been validated and what not. Since not all business logic can be at the data/parsing layer (esp. not in micro-architecture scenarios) it makes more sense to have as much as possible close to the business logic. This also reduces the potential for error because data will be validated very close to their actual use rather than once and then traveling through the system until the consumer can no longer be certain that it was validated as expected.

raderio commented 5 years ago

Each client tells in the request what API capabilities they support and the API server will adjust their functionality and response format accordingly to consider and/or compensate for missing capabilities.

Is this technique has a name, or maybe you can provide links to some articles?

it makes more sense to have as much as possible close to the business logic

yes, but it this case the validation is not so declarative, also if it is not done by annotations it is harder to do the documentation, because in case of annotations you can generate it

fluidsonic commented 5 years ago

Each client tells in the request what API capabilities they support and the API server will adjust their functionality and response format accordingly to consider and/or compensate for missing capabilities.

Is this technique has a name, or maybe you can provide links to some articles?

I've done that without checking if anyone else is doing that already, so if there is a name then I don't know it, nor do I know any articles. It was working very good though so maybe I should write an article about it :)

it makes more sense to have as much as possible close to the business logic

yes, but it this case the validation is not so declarative, also if it is not done by annotations it is harder to do the documentation, because in case of annotations you can generate it

I agree that documentation-wise it would be a lot simpler. If annotation-based validation works for you then this is totally fine to use. I'd do it directly in the data model rather than in the parsing layer though. And the codecs which are used for parsing then simply use the generated constructors or factory methods which in turn implement the validation. Wouldn't that work for you?

raderio commented 5 years ago

I've done that without checking if anyone else is doing that already, so if there is a name then I don't know it, nor do I know any articles.

Is it something like https://www.youtube.com/watch?v=M2KCu0Oq3JE ?

It was working very good though so maybe I should write an article about it

Will be great

fluidsonic commented 5 years ago

I've done that without checking if anyone else is doing that already, so if there is a name then I don't know it, nor do I know any articles.

Is it something like https://www.youtube.com/watch?v=M2KCu0Oq3JE ?

Exactly like that! Very interesting video with good ideas on pushing this forward. Thank you for sharing :)