跪拜 Guibai
← All articles
Java · Spring Boot

ValidX vs. Regex: When Business Validation Outgrows Pattern Matching

By vipxieliang ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

If your validation regex accepts garbage because it can't verify a checksum, this comparison shows a concrete way to fold algorithmic checks into annotations and cut maintenance when rules change, which matters for any application dealing with financial or identity data.

Summary

For years, Java developers have reached for regular expressions to validate phone numbers, email addresses, and ID numbers. But when validation moves beyond format and into value checks, regex hits a wall. This comparison walks through six real business scenarios, showing how a library called ValidX handles Chinese phone numbers, unified social credit codes, and bank cards with Luhn checks. Where regex requires a 30-character pattern that still can't verify a check digit, ValidX uses annotations like @ChinesePhone and @BankCard, which wrap precompiled regex for format screening and then run algorithmic checks for authenticity.

The article puts numbers on the tradeoff. Pure regex runs at about 0.3 microseconds per match, but it accepts many invalid values. ValidX's hybrid approach runs at 1.2 microseconds for valid input and 0.3 for invalid parts thanks to fail-fast logic, while pushing correctness past 99.9 percent. The library also carries internationalized error messages in nine languages and claims to cut maintenance when rules change, like a new phone prefix from the telecom regulator.

The author doesn't argue for abandoning regex. The recommendation is to use regex for simple format checks and ValidX for anything with check digits, frequent rule changes, or reuse across DTO fields. A migration guide outlines four steps: identify regex in the codebase, classify format versus business validation, replace with annotations or the chain API, and test for correctness and performance.

Takeaways
— ValidX provides annotations like @ChinesePhone, @ChineseIdCard, @BankCard, and @UnifiedSocialCreditCode that wrap both regex format checks and algorithmic checks.
— Pure regex cannot express Luhn or mod 31 checksum verification, so it only validates format, leaving false positives for cards and credit codes.
— The author's benchmark shows pure regex matching at ~0.3μs, while ValidX's hybrid runs at ~1.2μs for valid input and ~0.3μs for invalid due to fail-fast checks.
— ValidX claims a correctness rate above 99.9% for the tested scenarios, versus about 60% for regex-only format checks on Chinese identity numbers.
— The recommended approach is to keep regex for simple format checks (zip codes, IPs) and use ValidX for anything with check digits, frequent rule changes, or multi-field reuse.
— Migration follows four steps: identify all Pattern.compile uses, classify format vs. business validation, replace with annotations or chain API, and test for correctness and performance.
— ValidX includes error messages in nine languages, with semantics tailored to each locale.
Conclusions

The article is written by the library's author, so the performance numbers and maintenance claims come from the creator rather than an independent benchmark.

The fail-fast design is the key to keeping performance up: most invalid inputs are rejected in the first one or two steps, so the algorithmic checks only run on plausible values.

The comparison frames regex as a tool for format and ValidX as a wrapper that adds domain logic; this is a pragmatic hybrid that many teams already improvise with custom functions, but ValidX standardizes it.

The claim that ValidX 'wins' on readability is subjective, but the code examples do show that a one-line annotation is easier to review than a 100-character pattern with character classes.

Concepts & terms
Luhn algorithm
A simple checksum formula used to validate a variety of identification numbers, including credit card numbers. It involves doubling every second digit from the right and summing the digits of the result; the total must be divisible by 10.
Mod 31 check digit
Used in China's Unified Social Credit Code. The last character is a check digit computed from a weighted sum of the previous 17 characters using weights, then taking the remainder modulo 31.
Fail-fast validation
A design where validation stops at the first failing check, rejecting invalid input early without running expensive subsequent checks. In this context, length and regex checks run before algorithmic checksum verification.
Semantic annotations
Java annotations that declare validation rules declaratively, such as @ChinesePhone, which hides the underlying regex and algorithm implementation behind a readable name.
From the discussion
Featured comments
xiaomache

After all that, it's just wrapping it in another layer.

vipxieliang

Some are. Some have more complex validation logic, like ID cards and bank cards.

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗