-
-
Notifications
You must be signed in to change notification settings - Fork 6.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BUG] Golang pattern validation with regex fails on commas #20079
Comments
Currently investigating (with Java and Go, but I'm not using I would like to add to this issue a test case with another regex that causes me a trouble, if you agree: name:
type: string
pattern: "^[	!'&\"()*+,-./0-9:;<=>;?A-Z_a-z[]{}|^@#~]+$`" This one, also:
Name *string "json:\"name,omitempty\" validate:regex=\"/^[	!'&\\"()*+,-.\/0-9:;<=>;?A-Z_a-z[]{}|^@#~]+`$/\"" which is also invalid, another way, by a
So that, I add to remove that backtick character, resuming my regex in yaml's I did the first attempt you suggested, @DVasselli if (cp.pattern != null) {
String regex = String.format(Locale.getDefault(), "regex=\"%s\"", cp.pattern);
String validate = String.format(Locale.getDefault(), "validate:%s", regex);
cp.vendorExtensions.put(X_GO_CUSTOM_TAG, validate);
}
// construct data tag in the template: x-go-datatag
// originl template
// `json:"{{{baseName}}}{{^required}},omitempty{{/required}}"{{#withXml}} xml:"{{{baseName}}}{{#isXmlAttribute}},attr{{/isXmlAttribute}}"{{/withXml}}{{#withValidate}} validate:"{{validate}}"{{/withValidate}}{{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}`
String goDataTag = "json:\"" + cp.baseName;
if (!cp.required) {
goDataTag += ",omitempty";
}
goDataTag += "\"";
if (withXml) {
goDataTag += " xml:" + "\"" + cp.baseName;
if (cp.isXmlAttribute) {
goDataTag += ",attr";
}
goDataTag += "\"";
}
// {{#withValidate}} validate:"{{validate}}"{{/withValidate}}
if (Boolean.parseBoolean(String.valueOf(additionalProperties.getOrDefault("withValidate", "false")))) {
goDataTag += " validate:\"" + additionalProperties.getOrDefault("validate", "") + "\"";
}
// {{#vendorExtensions.x-go-custom-tag}} {{{.}}}{{/vendorExtensions.x-go-custom-tag}}
if (StringUtils.isNotEmpty(String.valueOf(cp.vendorExtensions.getOrDefault(X_GO_CUSTOM_TAG, "")))) {
goDataTag += " " + cp.vendorExtensions.get(X_GO_CUSTOM_TAG);
}
// if it contains backtick, wrap with " instead
if (goDataTag.contains("`")) {
goDataTag = " \"" + goDataTag.replace("\"", "\\\"") + "\"";
} else {
goDataTag = " `" + goDataTag + "`";
}
cp.vendorExtensions.put("x-go-datatag", goDataTag); Making Go client generator producing this, that looks nicer to me: // ImportCode struct for ImportCode
type ImportCode struct {
Code *string `json:"code,omitempty" validate:regex="/^[0-9]{2,}$/"`
Name *string `json:"name,omitempty" validate:regex="/^[	!'&\"()*+,-.\/0-9:;<=>;?A-Z_a-z[]{}|^@#~]+$/"`
} But it still doesn't work: go vet ./...
./model_import_code.go:22:2: struct field tag `json:"code,omitempty" validate:regex="/^[0-9]{2,}$/"` not compatible with reflect.StructTag.Get: bad syntax for struct tag value
./model_import_code.go:23:2: struct field tag `json:"name,omitempty" validate:regex="/^[	!'&\"()*+,-.\/0-9:;<=>;?A-Z_a-z[]{}|^@#~]+$/"` not compatible with reflect.StructTag.Get: bad syntax for struct tag value Removing Does anybody have a clue about what target expression should be enclosed into
|
@mlebihan thanks for looking into this! Looking at your generated code I found the following:
// ImportCode struct for ImportCode
type ImportCode struct {
Code *string `json:"code,omitempty" validate:"regexp=^[0-9]{2\\,}$"`
// Name field I am not sure I understand that regex...
} As per this:
The generator is generating code that uses this validation library https://github.com/go-validator/validator so the rules described in the read me should apply. In a nutshell, the struct tag should have this format As per the backtick Hope this helps |
I succeeded in correcting most of the generation, but I'm still a bit unease. See my fork, WIP. The second pattern I'm trying to compile for the
...even if it might produce no interesting matches: I've received a regex near that one, had to work it a bit to make it accepted by one online validator and then, whatever it is a clever one or not, it is syntactically correct (even in the case I would have broken its semantic and that it would become useless) and should be taken as it is. But I'll try to correct it, if I can, in order to have a complex but fully functional regexp. Whatever, I've almost succeeded: components:
schemas:
importCode:
type: object
properties:
code:
type: string
pattern: "^[0-9]{2,}$"
name:
type: string
pattern: "^[	!'&\"()*+,-./0-9:;<=>;?A-Z_a-z[]{}|^@#~]+`$" leads now to this fragment, that is accepted by type ImportCode struct {
Code *string `json:"code,omitempty" validate:"regexp=^[0-9]{2\\,}$"`
Name *string `json:"name,omitempty" validate:"regexp=^[	!'&\"()*+\\,-.\\0-9:;<=>;?A-Z_a-z[]{}|^@#~]+\x60$"`
} I have no clue why is it so, but it's by construction, for a long time and for all languages,
And then my Java statements are currently defective: /* We need to escape \ to \\
except if it is currently present in the string for the quote itself. Regexp:
\\[^"]
*/
String BACKSLASH_THAT_ISNT_AN_ESCAPED_QUOTE="\\\\[^\"]";
String ESCAPED_BACKSLASH_INTO_A_STRING_ITSELF = Matcher.quoteReplacement("\\\\");
validate = validate.replaceAll(BACKSLASH_THAT_ISNT_AN_ESCAPED_QUOTE, ESCAPED_BACKSLASH_INTO_A_STRING_ITSELF); They are here to prevent the escaping of the So: And I am not experienced a lot in regexp to correct this. |
So, I might be a bit naive here, but why are we doing all that manipulation on the incoming
I can help if you need, but I am not sure what you need help with |
If I remove the suspicious lines you've seen, and write this code instead: if (cp.pattern != null) {
LOGGER.info("Received pattern: {}", cp.pattern);
// Pattern might be enclosed into /.../ that aren't wished. Remove them.
String p = cp.pattern;
if (cp.pattern.startsWith("/") && cp.pattern.endsWith("/")) {
p = cp.pattern.substring(1, cp.pattern.length() - 1);
}
String regexp = String.format(Locale.getDefault(), "regexp=%s", p);
String validate = String.format(Locale.getDefault(), "validate:\"%s\"", regexp);
// Replace backtick by \\x60, if found
if (validate.contains("`")) {
validate = validate.replace("`", "\\x60");
}
// Escape comma
if (validate.contains(",")) {
validate = validate.replace(",", "\\\\,");
}
LOGGER.info("validate clause: {}", validate);
cp.vendorExtensions.put(X_GO_CUSTOM_TAG, validate);
} and that I choose for name:
type: string
pattern: "^/0-9$" Here are the logs I'm receiving during generation:
The This causes the whole generation to be defective soon: // ImportCode struct for ImportCode
type ImportCode struct {
Code *string `json:"code,omitempty" validate:"regexp=^[0-9]{2\\,}$"`
Name *string `json:"name,omitempty" validate:"regexp=^\/0-9$"`
} if that |
I see, but if you never gave that |
In protected void updatePropertyForString(CodegenProperty property, Schema p) {
if (ModelUtils.isByteArraySchema(p)) {
property.setIsString(false);
property.isByteArray = true;
} else if (ModelUtils.isBinarySchema(p)) {
property.isBinary = true;
property.isFile = true; // file = binary in OAS3
} else if (ModelUtils.isUUIDSchema(p)) {
property.isUuid = true;
} else if (ModelUtils.isURISchema(p)) {
property.isUri = true;
} else if (ModelUtils.isEmailSchema(p)) {
property.isEmail = true;
} else if (ModelUtils.isPasswordSchema(p)) {
property.isPassword = true;
} else if (ModelUtils.isDateSchema(p)) { // date format
property.setIsString(false); // for backward compatibility with 2.x
property.isDate = true;
} else if (ModelUtils.isDateTimeSchema(p)) { // date-time format
property.setIsString(false); // for backward compatibility with 2.x
property.isDateTime = true;
} else if (ModelUtils.isDecimalSchema(p)) { // type: string, format: number
property.isDecimal = true;
property.setIsString(false);
}
property.pattern = toRegularExpression(p.getPattern());
} that eventually causes this: public String addRegularExpressionDelimiter(String pattern) {
if (StringUtils.isEmpty(pattern)) {
return pattern;
}
if (!pattern.matches("^/.*")) {
return "/" + pattern.replaceAll("/", "\\\\/") + "/";
}
return pattern;
} I think the best thing I have to do is to save the pattern value just taken from |
I agree with the approach, and specifically with this:
Let me know if you need any support from me, please |
I went on an interesting page of regex samples with their matches and non-matches from SAP help I've added them to yaml, but I had to do few changes to enter them: openapi: '3.0.3'
info:
title: API Test
version: '1.0'
paths:
/foo:
get:
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
code:
oneOf:
- $ref: "#/components/schemas/importCode"
components:
schemas:
importCode:
type: object
properties:
code:
type: string
pattern: "^[0-9]{2,}$"
name:
description: "A very long and complex regex"
type: string
pattern: "^[	!'&\"()*+,-./0-9:;<=>;?A-Z_a-z[]{}|^@#~]+`$"
creditCard:
description: "Visa credit card\n
matches: 4123 6453 2222 1746\n
non-matches: 3124 5675 4400 4567, 4123-6453-2222-1746"
type: string
# found unknown escape character s if kept as \s
pattern: "^4[0-9]{3}\\s[0-9]{4}\\s[0-9]{4}\\s[0-9]{4}$"
date:
description: "Some dates\n
matches: 31/04/1999, 15/12/4567\n
non-matches: 31/4/1999, 31/4/99, 1999/04/19, 42/67/25456"
type: string
pattern: "^([0-2][0-9]|30|31)/(0[1-9]|1[0-2])/[0-9]{4}$"
windowsAbsolutePath:
description: "Windows absolute path\n
matches: \\\\server\\share\\file\n
non-matches: \\directory\\directory2, /directory2"
type: string
pattern: "^([A-Za-z]:|\\)\\[[:alnum:][:whitespace:]!"#$%&'()+,-.\\;=@\[\]^_`{}~.]*$"
email1:
description: "Email Address 1\n
matches: [email protected], [email protected]\n
non-matches: abc@dummy, ab*[email protected]"
type: string
# \- and \. rejected
pattern: "^[[:word:]\\-.]+@[[:word:]\\-.]+\\.[[:alpha:]]{2,3}$"
email2:
description: "Email Address 2\n
matches: *@[email protected], __1234^%@@abc.def.ghijkl\n
non-matches: abc.123.*&ca, ^%abcdefg123"
type: string
# \.. rejected => \\..
pattern: "^.+@.+\\..+$"
htmlHexadecimalColorCode1:
description: "HTML Hexadecimal Color Code 1\n
matches: AB1234, CCCCCC, 12AF3B\n
non-matches: 123G45, 12-44-CC"
type: string
pattern: "^[A-F0-9]{6}$"
htmlHexadecimalColorCode2:
description: "HTML Hexadecimal Color Code 2\n
matches: AB 11 00, CC 12 D3\n
non-matches: SS AB CD, AA BB CC DD, 1223AB"
type: string
# found unknown escape character s if kept as \s
pattern: "^[A-F0-9]{2}\\s[A-F0-9]{2}\\s[A-F0-9]{2}$"
ipAddress:
description: "IP Address\n
matches: 10.25.101.216\n
non-matches: 0.0.0, 256.89.457.02"
type: string
# \. ==> \\.
pattern: "^((2(5[0-5]|[0-4][0-9])|1([0-9][0-9])|([1-9][0-9])|[0-9])\\.){3}(2(5[0-5]|[0-4][0-9])|1([0-9][0-9])|([1-9][0-9])|[0-9])$"
javaComments:
description: "Java Comments\n
matches: Matches Java comments that are between /* and */, or one line comments prefaced by //\n
non-matches: a=1"
type: string
# \* ==> \\*
pattern: "^/\\*.*\\*/|//[^\n]*$"
money:
description: "\n
matches: $1.00, -$97.65
non-matches: $1, 1.00$, $-75.17"
type: string
# \+ => \\+ and \$ => \\$ and \. => \\.
pattern: "^(\\+|-)?\\$[0-9]*\\.[0-9]{2}$"
positiveNegativeDecimalValue:
description: "Positive, negative numbers, and decimal values\n
matches: +41, -412, 2, 7968412, 41, +41.1, -3.141592653
non-matches: ++41, 41.1.19, -+97.14"
type: string
# \+ => \\+ and \. => \\.
pattern: "^(\\+|-)?[0-9]+(\\.[0-9]+)?$"
password1:
description: "Passwords 1\n
matches: abcd, 1234, A1b2C3d4, 1a2B3\n
non-matches: abc, *ab12, abcdefghijkl"
type: string
pattern: "^[[:alnum:]]{4,10}$"
password2:
description: "Passwords 2\n
matches: AB_cd, A1_b2c3, a123_\n
non-matches: *&^g, abc, 1bcd"
type: string
# \w => \\w
pattern: "^[a-zA-Z]\\w{3,7}$"
phoneNumber:
description: "Phone Numbers\n
matches: 519-883-6898, 519 888 6898\n
non-matches: 888 6898, 5198886898, 519 883-6898"
type: string
# \s => \\s
pattern: "^([2-9][0-9]{2}-[2-9][0-9]{2}-[0-9]{4})|([2-9][0-9]{2}\\s[2-9][0-9]{2}\\s[0-9]{4})$"
sentence1:
description: "Sentences 1\n
matches: Hello, how are you?\n
non-matches: i am fine"
type: string
# \. ==> \\. and \? => \\?
pattern: "^[A-Z0-9].*(\\.|\\?|!)$"
sentence2:
description: "Sentences 2\n
matches: Hello, how are you?n
non-matches: i am fine"
type: string
pattern: "^[[:upper:]0-9].*[.?!]$"
socialSecurityNumber:
description: "Social Security Number\n
matches: 123-45-6789\n
non-matches: 123 45 6789, 123456789, 1234-56-7891"
type: string
pattern: "^[0-9]{3}-[0-9]{2}-[0-9]{4}$"
url:
description: "URL\n
matches: http://www.sample.com, www.sample.com\n
non-matches: http://sample.com, http://www.sample.comm"
type: string
# \. ==> \\.
pattern: "^(http://)?www\\.[a-zA-Z0-9]+\\.[a-zA-Z]{2,3}$" Alas, this yaml generates a Go model that isn't accepted. /*
API Test
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
API version: 1.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package openapi
import (
"encoding/json"
)
// checks if the ImportCode type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &ImportCode{}
// ImportCode struct for ImportCode
type ImportCode struct {
Code *string `json:"code,omitempty" validate:"regexp=^[0-9]{2\\,}$"`
// A very long and complex regex
Name *string `json:"name,omitempty" validate:"regexp=^[	!'&\",()*+\\,-./0-9:;<=>;?A-Z_a-z[]{}|^@#~]+\x60$"`
// Visa credit card matches: 4123 6453 2222 1746 non-matches: 3124 5675 4400 4567, 4123-6453-2222-1746
CreditCard *string `json:"creditCard,omitempty" validate:"regexp=^4[0-9]{3}\s[0-9]{4}\s[0-9]{4}\s[0-9]{4}$"`
// Some dates matches: 31/04/1999, 15/12/4567 non-matches: 31/4/1999, 31/4/99, 1999/04/19, 42/67/25456
Date *string `json:"date,omitempty" validate:"regexp=^([0-2][0-9]|30|31)/(0[1-9]|1[0-2])/[0-9]{4}$"`
// Windows absolute path matches: \\\\server\\share\\file non-matches: \\directory\\directory2, /directory2
WindowsAbsolutePath *string `json:"windowsAbsolutePath,omitempty" validate:"regexp=^([A-Za-z]:|\)\[[:alnum:][:whitespace:]!"`
// Email Address 1 matches: [email protected], [email protected] non-matches: abc@dummy, ab*[email protected]
Email1 *string `json:"email1,omitempty" validate:"regexp=^[[:word:]\-.]+@[[:word:]\-.]+\.[[:alpha:]]{2\\,3}$"`
// Email Address 2 matches: *@[email protected], __1234^%@@abc.def.ghijkl non-matches: abc.123.*&ca, ^%abcdefg123
Email2 *string `json:"email2,omitempty" validate:"regexp=^.+@.+\..+$"`
// HTML Hexadecimal Color Code 1 matches: AB1234, CCCCCC, 12AF3B non-matches: 123G45, 12-44-CC
HtmlHexadecimalColorCode1 *string `json:"htmlHexadecimalColorCode1,omitempty" validate:"regexp=^[A-F0-9]{6}$"`
// HTML Hexadecimal Color Code 2 matches: AB 11 00, CC 12 D3 non-matches: SS AB CD, AA BB CC DD, 1223AB
HtmlHexadecimalColorCode2 *string `json:"htmlHexadecimalColorCode2,omitempty" validate:"regexp=^[A-F0-9]{2}\s[A-F0-9]{2}\s[A-F0-9]{2}$"`
// IP Address matches: 10.25.101.216 non-matches: 0.0.0, 256.89.457.02
IpAddress *string `json:"ipAddress,omitempty" validate:"regexp=^((2(5[0-5]|[0-4][0-9])|1([0-9][0-9])|([1-9][0-9])|[0-9])\.){3}(2(5[0-5]|[0-4][0-9])|1([0-9][0-9])|([1-9][0-9])|[0-9])$"`
// Java Comments matches: Matches Java comments that are between /_* and *_/, or one line comments prefaced by // non-matches: a=1
JavaComments *string `json:"javaComments,omitempty" validate:"regexp=^/\*.*\*/|//[^
]*$"`
// matches: $1.00, -$97.65 non-matches: $1, 1.00$, $-75.17
Money *string `json:"money,omitempty" validate:"regexp=^(\+|-)?\$[0-9]*\.[0-9]{2}$"`
// Positive, negative numbers, and decimal values matches: +41, -412, 2, 7968412, 41, +41.1, -3.141592653 non-matches: ++41, 41.1.19, -+97.14
PositiveNegativeDecimalValue *string `json:"positiveNegativeDecimalValue,omitempty" validate:"regexp=^(\+|-)?[0-9]+(\.[0-9]+)?$"`
// Passwords 1 matches: abcd, 1234, A1b2C3d4, 1a2B3 non-matches: abc, *ab12, abcdefghijkl
Password1 *string `json:"password1,omitempty" validate:"regexp=^[[:alnum:]]{4\\,10}$"`
// Passwords 2 matches: AB_cd, A1_b2c3, a123_ non-matches: *&^g, abc, 1bcd
Password2 *string `json:"password2,omitempty" validate:"regexp=^[a-zA-Z]\w{3\\,7}$"`
// Phone Numbers matches: 519-883-6898, 519 888 6898 non-matches: 888 6898, 5198886898, 519 883-6898
PhoneNumber *string `json:"phoneNumber,omitempty" validate:"regexp=^([2-9][0-9]{2}-[2-9][0-9]{2}-[0-9]{4})|([2-9][0-9]{2}\s[2-9][0-9]{2}\s[0-9]{4})$"`
// Sentences 1 matches: Hello, how are you? non-matches: i am fine
Sentence1 *string `json:"sentence1,omitempty" validate:"regexp=^[A-Z0-9].*(\.|\?|!)$"`
// Sentences 2 matches: Hello, how are you?n non-matches: i am fine
Sentence2 *string `json:"sentence2,omitempty" validate:"regexp=^[[:upper:]0-9].*[.?!]$"`
// Social Security Number matches: 123-45-6789 non-matches: 123 45 6789, 123456789, 1234-56-7891
SocialSecurityNumber *string `json:"socialSecurityNumber,omitempty" validate:"regexp=^[0-9]{3}-[0-9]{2}-[0-9]{4}$"`
// URL matches: http://www.sample.com, www.sample.com non-matches: http://sample.com, http://www.sample.comm
Url *string `json:"url,omitempty" validate:"regexp=^(http://)?www\.[a-zA-Z0-9]+\.[a-zA-Z]{2\\,3}$"`
}
// [...]
So the handling of that issue isn't finished. |
The last push in my fork is now able to accept a The problem to pass is that before the It's boring, because when one sets for regex Now, this openapi: '3.0.3'
info:
title: API Test
version: '1.0'
paths:
/foo:
get:
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
code:
oneOf:
- $ref: "#/components/schemas/importCode"
components:
schemas:
importCode:
type: object
properties:
code:
type: string
pattern: "^[0-9]{2,}$"
creditCard:
description: "Visa credit card\n
matches: 4123 6453 2222 1746\n
non-matches: 3124 5675 4400 4567, 4123-6453-2222-1746"
type: string
pattern: "^4[0-9]{3}\\s[0-9]{4}\\s[0-9]{4}\\s[0-9]{4}$"
# Original was: 4[0-9]{3}\s[0-9]{4}\s[0-9]{4}\s[0-9]{4}
date:
description: "Some dates\n
matches: 31/04/1999, 15/12/4567\n
non-matches: 31/4/1999, 31/4/99, 1999/04/19, 42/67/25456"
type: string
pattern: "^([0-2][0-9]|30|31)/(0[1-9]|1[0-2])/[0-9]{4}$"
# Original was: ([0-2][0-9]|30|31)/(0[1-9]|1[0-2])/[0-9]{4} : unchanged
windowsAbsolutePath:
description: "Windows absolute path\n
matches: \\\\server\\share\\file\n
non-matches: \\directory\\directory2, /directory2"
type: string
# This test case doesn't work due to a problem (?) in validator.v2 (?)
# it issues an unexpected unknown tag or Bad Parameter.
# pattern: "^([A-Za-z]:|\\)\\[[:alnum:][:whitespace:]!\"#$%&'()+,-.;=@[]^_`{}~.]*$"
# Original was: ([A-Za-z]:|\\)\\[[:alnum:][:whitespace:]!"#$%&'()+,-.\\;=@\[\]^_`{}~.]*
email1:
description: "Email Address 1\n
matches: [email protected], [email protected]\n
non-matches: abc@dummy, ab*[email protected]"
type: string
pattern: "^[[:word:]\\-.]+@[[:word:]\\-.]+\\.[[:alpha:]]{2,3}$"
# Original was: [[:word:]\-.]+@[[:word:]\-.]+\.[[:alpha:]]{2,3}
email2:
description: "Email Address 2\n
matches: *@[email protected], __1234^%@@abc.def.ghijkl\n
non-matches: abc.123.*&ca, ^%abcdefg123"
type: string
pattern: "^.+@.+\\..+$"
# Original was: .+@.+\..+
htmlHexadecimalColorCode1:
description: "HTML Hexadecimal Color Code 1\n
matches: AB1234, CCCCCC, 12AF3B\n
non-matches: 123G45, 12-44-CC"
type: string
pattern: "^[A-F0-9]{6}$"
# Original was: [A-F0-9]{6} : unchanged
htmlHexadecimalColorCode2:
description: "HTML Hexadecimal Color Code 2\n
matches: AB 11 00, CC 12 D3\n
non-matches: SS AB CD, AA BB CC DD, 1223AB"
type: string
pattern: "^[A-F0-9]{2}\\s[A-F0-9]{2}\\s[A-F0-9]{2}$"
# Original was: [A-F0-9]{2}\s[A-F0-9]{2}\s[A-F0-9]{2}
ipAddress:
description: "IP Address\n
matches: 10.25.101.216\n
non-matches: 0.0.0, 256.89.457.02"
type: string
pattern: "^((2(5[0-5]|[0-4][0-9])|1([0-9][0-9])|([1-9][0-9])|[0-9])\\.){3}(2(5[0-5]|[0-4][0-9])|1([0-9][0-9])|([1-9][0-9])|[0-9])$"
# Original was: ((2(5[0-5]|[0-4][0-9])|1([0-9][0-9])|([1-9][0-9])|[0-9])\.){3}(2(5[0-5]|[0-4][0-9])|1([0-9][0-9])|([1-9][0-9])|[0-9])
javaComments:
description: "Java Comments\n
matches: Matches Java comments that are between /* and */, or one line comments prefaced by //\n
non-matches: a=1"
type: string
# This test case doesn't work due to a problem (?) in validator.v2 (?)
# org.yaml.snakeyaml.scanner declares \* being an invalid escape code at yaml checking step
# pattern: "^/\*.*\*/|//[^\\n]*$"
# Original was: /\*.*\*/|//[^\n]*
money:
description: "\n
matches: $1.00, -$97.65
non-matches: $1, 1.00$, $-75.17"
type: string
pattern: "^(\\+|-)?\\$[0-9]*\\.[0-9]{2}$"
# Original was: (\+|-)?\$[0-9]*\.[0-9]{2}
positiveNegativeDecimalValue:
description: "Positive, negative numbers, and decimal values\n
matches: +41, -412, 2, 7968412, 41, +41.1, -3.141592653
non-matches: ++41, 41.1.19, -+97.14"
type: string
pattern: "^(\\+|-)?[0-9]+(\\.[0-9]+)?$"
# Original was: (\+|-)?[0-9]+(\.[0-9]+)?
password1:
description: "Passwords 1\n
matches: abcd, 1234, A1b2C3d4, 1a2B3\n
non-matches: abc, *ab12, abcdefghijkl"
type: string
pattern: "^[[:alnum:]]{4,10}$"
# Original was: [[:alnum:]]{4,10} : unchanged
password2:
description: "Passwords 2\n
matches: AB_cd, A1_b2c3, a123_\n
non-matches: *&^g, abc, 1bcd"
type: string
pattern: "^[a-zA-Z]\\w{3,7}$"
# Original was: [a-zA-Z]\w{3,7} : unchanged
phoneNumber:
description: "Phone Numbers\n
matches: 519-883-6898, 519 888 6898\n
non-matches: 888 6898, 5198886898, 519 883-6898"
type: string
pattern: "^([2-9][0-9]{2}-[2-9][0-9]{2}-[0-9]{4})|([2-9][0-9]{2}\\s[2-9][0-9]{2}\\s[0-9]{4})$"
# Original was: ([2-9][0-9]{2}-[2-9][0-9]{2}-[0-9]{4})|([2-9][0-9]{2}\s[2-9][0-9]{2}\s[0-9]{4})
sentence1:
description: "Sentences 1\n
matches: Hello, how are you?\n
non-matches: i am fine"
type: string
pattern: "^[A-Z0-9].*(\\.|\\?|!)$"
# Original was: [A-Z0-9].*(\.|\?|!)
sentence2:
description: "Sentences 2\n
matches: Hello, how are you?n
non-matches: i am fine"
type: string
pattern: "^[[:upper:]0-9].*[.?!]$"
# Original was: [[:upper:]0-9].*[.?!] : unchanged
socialSecurityNumber:
description: "Social Security Number\n
matches: 123-45-6789\n
non-matches: 123 45 6789, 123456789, 1234-56-7891"
type: string
pattern: "^[0-9]{3}-[0-9]{2}-[0-9]{4}$"
# Original was: [0-9]{3}-[0-9]{2}-[0-9]{4} : unchanged
url:
description: "URL\n
matches: http://www.sample.com, www.sample.com\n
non-matches: http://sample.com, http://www.sample.comm"
type: string
# \. ==> \\.
pattern: "^(http://)?www\\.[a-zA-Z0-9]+\\.[a-zA-Z]{2,3}$"
# Original was: (http://)?www\.[a-zA-Z0-9]+\.[a-zA-Z]{2,3} generates this (considering two issues remaining with test cases, see further comment): type ImportCode struct {
Code *string `json:"code,omitempty" validate:"regexp=^[0-9]{2\\,}$"`
// Visa credit card matches: 4123 6453 2222 1746 non-matches: 3124 5675 4400 4567, 4123-6453-2222-1746
CreditCard *string `json:"creditCard,omitempty" validate:"regexp=^4[0-9]{3}\\s[0-9]{4}\\s[0-9]{4}\\s[0-9]{4}$"`
// Some dates matches: 31/04/1999, 15/12/4567 non-matches: 31/4/1999, 31/4/99, 1999/04/19, 42/67/25456
Date *string `json:"date,omitempty" validate:"regexp=^([0-2][0-9]|30|31)/(0[1-9]|1[0-2])/[0-9]{4}$"`
// Windows absolute path matches: \\\\server\\share\\file non-matches: \\directory\\directory2, /directory2
WindowsAbsolutePath *string `json:"windowsAbsolutePath,omitempty"`
// Email Address 1 matches: [email protected], [email protected] non-matches: abc@dummy, ab*[email protected]
Email1 *string `json:"email1,omitempty" validate:"regexp=^[[:word:]\\-.]+@[[:word:]\\-.]+\\.[[:alpha:]]{2\\,3}$"`
// Email Address 2 matches: *@[email protected], __1234^%@@abc.def.ghijkl non-matches: abc.123.*&ca, ^%abcdefg123
Email2 *string `json:"email2,omitempty" validate:"regexp=^.+@.+\\..+$"`
// HTML Hexadecimal Color Code 1 matches: AB1234, CCCCCC, 12AF3B non-matches: 123G45, 12-44-CC
HtmlHexadecimalColorCode1 *string `json:"htmlHexadecimalColorCode1,omitempty" validate:"regexp=^[A-F0-9]{6}$"`
// HTML Hexadecimal Color Code 2 matches: AB 11 00, CC 12 D3 non-matches: SS AB CD, AA BB CC DD, 1223AB
HtmlHexadecimalColorCode2 *string `json:"htmlHexadecimalColorCode2,omitempty" validate:"regexp=^[A-F0-9]{2}\\s[A-F0-9]{2}\\s[A-F0-9]{2}$"`
// IP Address matches: 10.25.101.216 non-matches: 0.0.0, 256.89.457.02
IpAddress *string `json:"ipAddress,omitempty" validate:"regexp=^((2(5[0-5]|[0-4][0-9])|1([0-9][0-9])|([1-9][0-9])|[0-9])\\.){3}(2(5[0-5]|[0-4][0-9])|1([0-9][0-9])|([1-9][0-9])|[0-9])$"`
// Java Comments matches: Matches Java comments that are between /_* and *_/, or one line comments prefaced by // non-matches: a=1
JavaComments *string `json:"javaComments,omitempty"`
// matches: $1.00, -$97.65 non-matches: $1, 1.00$, $-75.17
Money *string `json:"money,omitempty" validate:"regexp=^(\\+|-)?\\$[0-9]*\\.[0-9]{2}$"`
// Positive, negative numbers, and decimal values matches: +41, -412, 2, 7968412, 41, +41.1, -3.141592653 non-matches: ++41, 41.1.19, -+97.14
PositiveNegativeDecimalValue *string `json:"positiveNegativeDecimalValue,omitempty" validate:"regexp=^(\\+|-)?[0-9]+(\\.[0-9]+)?$"`
// Passwords 1 matches: abcd, 1234, A1b2C3d4, 1a2B3 non-matches: abc, *ab12, abcdefghijkl
Password1 *string `json:"password1,omitempty" validate:"regexp=^[[:alnum:]]{4\\,10}$"`
// Passwords 2 matches: AB_cd, A1_b2c3, a123_ non-matches: *&^g, abc, 1bcd
Password2 *string `json:"password2,omitempty" validate:"regexp=^[a-zA-Z]\\w{3\\,7}$"`
// Phone Numbers matches: 519-883-6898, 519 888 6898 non-matches: 888 6898, 5198886898, 519 883-6898
PhoneNumber *string `json:"phoneNumber,omitempty" validate:"regexp=^([2-9][0-9]{2}-[2-9][0-9]{2}-[0-9]{4})|([2-9][0-9]{2}\\s[2-9][0-9]{2}\\s[0-9]{4})$"`
// Sentences 1 matches: Hello, how are you? non-matches: i am fine
Sentence1 *string `json:"sentence1,omitempty" validate:"regexp=^[A-Z0-9].*(\\.|\\?|!)$"`
// Sentences 2 matches: Hello, how are you?n non-matches: i am fine
Sentence2 *string `json:"sentence2,omitempty" validate:"regexp=^[[:upper:]0-9].*[.?!]$"`
// Social Security Number matches: 123-45-6789 non-matches: 123 45 6789, 123456789, 1234-56-7891
SocialSecurityNumber *string `json:"socialSecurityNumber,omitempty" validate:"regexp=^[0-9]{3}-[0-9]{2}-[0-9]{4}$"`
// URL matches: http://www.sample.com, www.sample.com non-matches: http://sample.com, http://www.sample.comm
Url *string `json:"url,omitempty" validate:"regexp=^(http://)?www\\.[a-zA-Z0-9]+\\.[a-zA-Z]{2\\,3}$"`
} That is accepted. I have to write a test now to ensure that all these regexp are matching the samples they shall and not matching those they shouldn't. |
Submitted as PR, with the following mentions: In a struct, for a
Test cases added18 new regular expressions has been taken for test cases, from an SAP help page. A go test has been run with various values, and it succeeds except for one test case: Tests are in
The following command should then show the success: go mod tidy && go vet ./... && go test ./... -v Remaining problemThis fix mostly fixes the handling of regular expressions with Go.
|
Bug Report Checklist
Description
When having a struct with a
oneOf
keyword which has an item with a regex validation, if the regex has a comma, the validation will always fail.For example, if I want a number to be present 2 or more times
[0-9]{2,}
, this would fail since the validator library wants us to escape the comma.Furthermore, the error message says
data failed to match schemas in oneOf
which is misleading since the error is really coming from the regex validation.openapi-generator version
7.9.0
OpenAPI declaration file content or url
Generation Details
From the folder where you put the yml file (I am working in
~/playground
):openapi-generator generate -i api_test.yml \ -g go \ -o ~/playground/gen \ --package-name=foo \ --global-property=verbose=false,apiDocs=false,apiTests=false,modelDocs=false,modelTests=false \ --additional-properties=isGoSubmodule=true,withGoMod=false
Steps to reproduce
foo_test.go
file like the following:This will fail at unmarshalling no matter how many digits you put on that string.
3. To prove the point, edit the yml file removing the comma, regenerate, and provide exactly 2 digits in the test. This will succeed.
4. Bonus point, if on the file with an exact number of repetition (without the comma) you put more than expected, the error will say
data failed to match schemas in oneOf
which is too generic for regex validation failure.Related issues/PRs
None
Suggest a fix
From where I stand, there are 2 possible issues:
openapi-generator/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractGoCodegen.java
Lines 789 to 791 in 85f7112
The text was updated successfully, but these errors were encountered: