-
Notifications
You must be signed in to change notification settings - Fork 2.2k
[Fix][Transform-V2][JsonPath] Fix date/time conversion error when mul… #10390
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
base: dev
Are you sure you want to change the base?
Conversation
…tiple date columns exist
|
Please enable CI following the instructions. |
dybyte
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should add null checks in JsonRowConverters#convertToLocalDate and JsonRowConverters#convertToLocalDateTime.
Also, could you add test cases for these two methods in JsonRowDataSerDeSchemaTest?
|
There is currently a problem with CI, and you need to enable it. |
|
Thanks for the review! I’ll add null checks to |
Issue 1: Test coverage is not comprehensive enoughLocation: Related Context:
Problem Description: The newly added test cases cover the scenarios of "multiple date columns with different formats" and "containing null values", but are missing the following scenarios:
Potential Risks:
Impact Scope:
Severity: MINOR Improvement Suggestions: @Test
public void testSingleDateColumn() {
// Verify that the behavior of a single date column remains consistent with the modifications
Map<String, Object> configMap = new HashMap<>();
configMap.put(
JsonPathTransformConfig.COLUMNS.key(),
Arrays.asList(
ImmutableMap.of(
JsonPathTransformConfig.SRC_FIELD.key(), "data",
JsonPathTransformConfig.PATH.key(), "$.birth",
JsonPathTransformConfig.DEST_FIELD.key(), "birth_date",
JsonPathTransformConfig.DEST_TYPE.key(), "date")));
// ... test logic
}
@Test
public void testMultipleDateColumnsWithSameFormat() {
// Verify that multiple date columns with the same format can share cache
Map<String, Object> configMap = new HashMap<>();
configMap.put(
JsonPathTransformConfig.COLUMNS.key(),
Arrays.asList(
ImmutableMap.of(..., "birth", "birth_date", "date"),
ImmutableMap.of(..., "hired", "hire_date", "date")));
String jsonData = "{\"birth\": \"2024-01-15\", \"hired\": \"2024-02-20\"}";
// ... verify both fields are correctly parsed
}
@Test
public void testMixedTypeColumns() {
// Verify mixed configuration of date columns with string and integer columns
Map<String, Object> configMap = new HashMap<>();
configMap.put(
JsonPathTransformConfig.COLUMNS.key(),
Arrays.asList(
ImmutableMap.of(..., "date_field", "date"),
ImmutableMap.of(..., "string_field", "string"),
ImmutableMap.of(..., "int_field", "int")));
// ... verify all types are correctly converted
}Rationale:
Issue 4: Insufficient encapsulability of fieldFormatterMapLocation: Related Context:
Problem Description:
Potential Risks:
Impact Scope:
Severity: MINOR Improvement Suggestions: // Current (line 80)
public Map<String, DateTimeFormatter> fieldFormatterMap = new HashMap<>();
// Suggested change to
private Map<String, DateTimeFormatter> fieldFormatterMap = new HashMap<>();
// If tests need access, add package-level visible access methods
Map<String, DateTimeFormatter> getFieldFormatterMap() {
return fieldFormatterMap;
}
// Or provide controlled access methods
public DateTimeFormatter getCachedFormatter(String fieldName) {
return fieldFormatterMap.get(fieldName);
}Rationale:
Note: This issue is outside the scope of this PR and is an existing problem in the codebase. However, since it was discovered during review, it should be recorded for future improvement. |
…tiple date columns exist
…tiple date columns exist
…n' into fix/jsonpath-destfield-conversion
|
@dybyte @DanielCarter-stack Thanks for the detailed reviews! I've added the following test cases to cover the requested scenarios: JsonPathTransformTest
JsonRowDataSerDeSchemaTest
@DanielCarter-stack I'm also interested in working on issue 4. Will create a follow-up PR after this one is merged. Please review when you have time. |
| private LocalDate convertToLocalDate(JsonNode jsonNode, String fieldName) { | ||
| String dateStr = jsonNode.asText(); | ||
|
|
||
| if (dateStr == null || dateStr.trim().isEmpty()) { | ||
| return null; | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should check fieldName for null rather than dateStr.
If fieldName is null, we shouldn’t put this entry into fieldFormatterMap.
|
|
||
| if (datetimeStr == null || datetimeStr.trim().isEmpty()) { | ||
| return null; | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
| @Test | ||
| public void testConvertToLocalDateWithEmptyString() throws IOException { | ||
| SeaTunnelRowType rowType = | ||
| new SeaTunnelRowType( | ||
| new String[] {"date_field"}, | ||
| new SeaTunnelDataType<?>[] {LocalTimeType.LOCAL_DATE_TYPE}); | ||
| JsonDeserializationSchema deserializationSchema = | ||
| new JsonDeserializationSchema(false, false, rowType); | ||
|
|
||
| // Test empty string | ||
| String emptyDateJson = "{\"date_field\":\"\"}"; | ||
| SeaTunnelRow row = deserializationSchema.deserialize(emptyDateJson.getBytes()); | ||
| assertNull(row.getField(0)); | ||
|
|
||
| // Test whitespace only string | ||
| String whitespaceJson = "{\"date_field\":\" \"}"; | ||
| row = deserializationSchema.deserialize(whitespaceJson.getBytes()); | ||
| assertNull(row.getField(0)); | ||
|
|
||
| // Test normal date value still works | ||
| String normalDateJson = "{\"date_field\":\"2024-01-15\"}"; | ||
| row = deserializationSchema.deserialize(normalDateJson.getBytes()); | ||
| assertEquals(LocalDate.of(2024, 1, 15), row.getField(0)); | ||
| } | ||
|
|
||
| @Test | ||
| public void testConvertToLocalDateTimeWithEmptyString() throws IOException { | ||
| SeaTunnelRowType rowType = | ||
| new SeaTunnelRowType( | ||
| new String[] {"timestamp_field"}, | ||
| new SeaTunnelDataType<?>[] {LocalTimeType.LOCAL_DATE_TIME_TYPE}); | ||
| JsonDeserializationSchema deserializationSchema = | ||
| new JsonDeserializationSchema(false, false, rowType); | ||
|
|
||
| // Test empty string | ||
| String emptyTimestampJson = "{\"timestamp_field\":\"\"}"; | ||
| SeaTunnelRow row = deserializationSchema.deserialize(emptyTimestampJson.getBytes()); | ||
| assertNull(row.getField(0)); | ||
|
|
||
| // Test whitespace only string | ||
| String whitespaceJson = "{\"timestamp_field\":\" \"}"; | ||
| row = deserializationSchema.deserialize(whitespaceJson.getBytes()); | ||
| assertNull(row.getField(0)); | ||
|
|
||
| // Test normal timestamp value still works | ||
| String normalTimestampJson = "{\"timestamp_field\":\"2024-01-15 10:30:00\"}"; | ||
| row = deserializationSchema.deserialize(normalTimestampJson.getBytes()); | ||
| assertEquals(LocalDateTime.of(2024, 1, 15, 10, 30, 0), row.getField(0)); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these tests related to the current PR? I’m not entirely sure about the connection.
| Assertions.assertThrows( | ||
| Exception.class, () -> transform.map(new SeaTunnelRow(new Object[] {jsonData}))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use a more specific exception type here instead of Exception.class?
| Assertions.assertThrows( | ||
| Exception.class, () -> transform.map(new SeaTunnelRow(new Object[] {jsonData}))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
Fixes: #10333
Purpose of this pull request
When using JsonPath transform with multiple date/timestamp columns, the converter received
nullas the field name, causing incorrect date format resolution.Fixed by passing
columnConfig.getDestField()to the converter, ensuring each column resolves its own date format correctly.Does this PR introduce any user-facing change?
Yes. Previously, multiple date/timestamp columns in JsonPath transform could fail or produce incorrect results due to missing field name context. Now each column correctly applies its configured date/time format.
How was this patch tested?
Check list
New License Guide
incompatible-changes.mdto describe the incompatibility caused by this PR.