Skip to content

Conversation

@jujn
Copy link
Contributor

@jujn jujn commented Dec 12, 2025

What this PR does / why we need it?

Summary of your change

Please indicate you've done the following:

  • Made sure tests are passing and test coverage is added if needed.
  • Made sure commit message follow the rule of Conventional Commits specification.
  • Considered the docs impact and opened a new docs issue or PR with docs changes if needed.

Copilot AI review requested due to automatic review settings December 12, 2025 09:09
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements support for custom error messages in JSON schema validation, addressing issue #1559. The implementation uses the Template Method pattern to intercept validation results and replace error messages when a custom message is defined.

Key changes:

  • Refactored all validate() methods to validateInternal() in schema implementations
  • Added wrapper validate() methods in the base JSONSchema class that apply custom error messages
  • Added support for both errorMessage and message properties in schema definitions

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
JSONSchema.java Added customErrorMessage field and refactored validation to use Template Method pattern with wrapper methods
IntegerSchema.java Renamed validate() methods to validateInternal() to support custom error message interception
NumberSchema.java Renamed validate() methods to validateInternal() to support custom error message interception
StringSchema.java Renamed validate() method to validateInternal() to support custom error message interception
ObjectSchema.java Renamed validate() method to validateInternal() to support custom error message interception
ArraySchema.java Renamed validate() method to validateInternal() to support custom error message interception
BooleanSchema.java Renamed validate() method to validateInternal() to support custom error message interception
EnumSchema.java Renamed validate() method to validateInternal() to support custom error message interception
NullSchema.java Renamed validate() method to validateInternal() to support custom error message interception
AllOf.java Renamed validate() method to validateInternal() to support custom error message interception
AnyOf.java Renamed validate() method to validateInternal() to support custom error message interception
OneOf.java Renamed validate() method to validateInternal() to support custom error message interception
Not.java Renamed validate() method to validateInternal() to support custom error message interception
Any.java Renamed validate() method to validateInternal() to support custom error message interception
UnresolvedReference.java Renamed validate() method to validateInternal() to support custom error message interception
CustomErrorMessageTest.java Added comprehensive test coverage for custom error messages including integer validation, string patterns, nested objects, and annotation-based schemas

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +66 to +74
@Test
public void testAnnotationSchemaMessage() {
String json = "{\"age\": 5}";
try {
JSON.parseObject(json, User.class);
} catch (JSONSchemaValidException e) {
Assertions.assertEquals("Age too young", e.getMessage());
}
}
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test expects an exception to be thrown but does not assert that it was actually thrown. If no exception occurs, the test will silently pass. Add an assertion after the try-catch block to fail the test if the expected exception was not thrown.

Copilot uses AI. Check for mistakes.

public ValidateResult validate(Long value) {
return validate((Object) value);
public final ValidateResult validate(Float value) {
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method JSONSchema.validate(..) could be confused with overloaded method validate, since dispatch depends on static types.

Copilot uses AI. Check for mistakes.

public ValidateResult validate(Integer value) {
return validate((Object) value);
protected ValidateResult validateInternal(Float value) {
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method JSONSchema.validateInternal(..) could be confused with overloaded method validateInternal, since dispatch depends on static types.

Copilot uses AI. Check for mistakes.

public ValidateResult validate(Double value) {
return validate((Object) value);
public final ValidateResult validate(Long value) {
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method JSONSchema.validate(..) could be confused with overloaded method validate, since dispatch depends on static types.
Method JSONSchema.validate(..) could be confused with overloaded method validate, since dispatch depends on static types.

Copilot uses AI. Check for mistakes.

public ValidateResult validate(Float value) {
return validate((Object) value);
protected ValidateResult validateInternal(Long value) {
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method JSONSchema.validateInternal(..) could be confused with overloaded method validateInternal, since dispatch depends on static types.
Method JSONSchema.validateInternal(..) could be confused with overloaded method validateInternal, since dispatch depends on static types.

Copilot uses AI. Check for mistakes.
return validateInternal((Object) value);
}

public final ValidateResult validate(Double value) {
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method JSONSchema.validate(..) could be confused with overloaded method validate, since dispatch depends on static types.

Copilot uses AI. Check for mistakes.
Comment on lines 772 to 775
protected ValidateResult validateInternal(Double value) {
return validateInternal((Object) value);
}

Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method JSONSchema.validateInternal(..) could be confused with overloaded method validateInternal, since dispatch depends on static types.

Suggested change
protected ValidateResult validateInternal(Double value) {
return validateInternal((Object) value);
}

Copilot uses AI. Check for mistakes.
return validateInternal((Object) value);
}

public final ValidateResult validate(double value) {
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method JSONSchema.validate(..) could be confused with overloaded method validate, since dispatch depends on static types.

Copilot uses AI. Check for mistakes.
Comment on lines 749 to 775
protected ValidateResult validateInternal(long value) {
return validateInternal((Object) value);
}

public final ValidateResult validate(long value) {
ValidateResult result = validateInternal(value);
if (!result.isSuccess() && customErrorMessage != null) {
return new ValidateResult(false, customErrorMessage);
}
return result;
}
protected ValidateResult validateInternal(double value) {
return validateInternal((Object) value);
}

public final ValidateResult validate(double value) {
ValidateResult result = validateInternal(value);
if (!result.isSuccess() && customErrorMessage != null) {
return new ValidateResult(false, customErrorMessage);
}
return result;
}

protected ValidateResult validateInternal(Double value) {
return validateInternal((Object) value);
}

Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method JSONSchema.validateInternal(..) could be confused with overloaded method validateInternal, since dispatch depends on static types.

Suggested change
protected ValidateResult validateInternal(long value) {
return validateInternal((Object) value);
}
public final ValidateResult validate(long value) {
ValidateResult result = validateInternal(value);
if (!result.isSuccess() && customErrorMessage != null) {
return new ValidateResult(false, customErrorMessage);
}
return result;
}
protected ValidateResult validateInternal(double value) {
return validateInternal((Object) value);
}
public final ValidateResult validate(double value) {
ValidateResult result = validateInternal(value);
if (!result.isSuccess() && customErrorMessage != null) {
return new ValidateResult(false, customErrorMessage);
}
return result;
}
protected ValidateResult validateInternal(Double value) {
return validateInternal((Object) value);
}
public final ValidateResult validate(long value) {
ValidateResult result = validateInternal((Object) value);
if (!result.isSuccess() && customErrorMessage != null) {
return new ValidateResult(false, customErrorMessage);
}
return result;
}
public final ValidateResult validate(double value) {
ValidateResult result = validateInternal((Object) value);
if (!result.isSuccess() && customErrorMessage != null) {
return new ValidateResult(false, customErrorMessage);
}
return result;
}

Copilot uses AI. Check for mistakes.
public abstract ValidateResult validate(Object value);
protected abstract ValidateResult validateInternal(Object value);

public final ValidateResult validate(Object value) {
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method JSONSchema.validate(..) could be confused with overloaded method ObjectSchema.validate, since dispatch depends on static types.

Copilot uses AI. Check for mistakes.
@wenshao
Copy link
Member

wenshao commented Dec 14, 2025

errorMessage字段太长了,是不是可以用error就可以了?

@jujn
Copy link
Contributor Author

jujn commented Dec 14, 2025

errorMessage字段太长了,是不是可以用error就可以了?

好的,我加一下

@wenshao wenshao merged commit d86f135 into alibaba:main Dec 15, 2025
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants