Background
spark-rapids-jni's from_json_to_structs (see #4536) replicates Spark's depth-1 parent-NULL policy by reading the side-channel json_reader_diagnostics.top_level_columns_with_schema_mismatch returned by read_json_with_diagnostics and applying ALL_NULL to any top-level column flagged there.
Problem
The diagnostic is column-level, not row-level. cuDF reports that column X has SOME row(s) with a schema mismatch, but not which rows. Our workaround nulls the entire column, which over-nulls valid rows in a mixed-row batch:
Input rows for schema (data: struct<c1: int, c2: array<struct<c3, c4>>>):
{"data": {"c2": [{"c3": 19, "c4": "x"}], "c1": 1}} // valid
{"data": {"c2": [19], "c1": 2}} // c2 is int, schema says struct
Expected (Spark): row 1 = Row(c1=1, c2=Array(Row(19,"x"))), row 2 = null
Actual (cuDF + current spark-rapids-jni workaround): both rows null.
Proposal
Add a row-level field to json_reader_diagnostics, e.g.
struct json_reader_diagnostics {
std::vector<std::string> top_level_columns_with_schema_mismatch; // existing
std::unordered_map<std::string, std::vector<cudf::size_type>>
top_level_columns_with_schema_mismatch_rows; // new
};
mapping column name → sorted vector of mismatched row indices for that column.
With this, the spark-rapids-jni loop can null only the affected rows (e.g. via cudf::detail::valid_if on a boolean column-of-rows mask), matching Spark's per-row depth-1 behavior exactly.
Notes
- Column-level diagnostic stays in place for backward compatibility.
- Row indices are already maintained inside the JSON reader during the schema-category check; surfacing them in the diagnostic struct should be a localized change.
Affected
- spark-rapids-jni#4536 — Spark parity workaround that this would close out.
- Any downstream consumer that needs Spark/Jackson-style
isRoot=false nested-error-to-NULL propagation.
Background
spark-rapids-jni'sfrom_json_to_structs(see #4536) replicates Spark's depth-1 parent-NULL policy by reading the side-channeljson_reader_diagnostics.top_level_columns_with_schema_mismatchreturned byread_json_with_diagnosticsand applyingALL_NULLto any top-level column flagged there.Problem
The diagnostic is column-level, not row-level. cuDF reports that column X has SOME row(s) with a schema mismatch, but not which rows. Our workaround nulls the entire column, which over-nulls valid rows in a mixed-row batch:
Input rows for schema
(data: struct<c1: int, c2: array<struct<c3, c4>>>):Expected (Spark): row 1 =
Row(c1=1, c2=Array(Row(19,"x"))), row 2 =nullActual (cuDF + current spark-rapids-jni workaround): both rows null.
Proposal
Add a row-level field to
json_reader_diagnostics, e.g.mapping column name → sorted vector of mismatched row indices for that column.
With this, the spark-rapids-jni loop can null only the affected rows (e.g. via
cudf::detail::valid_ifon a boolean column-of-rows mask), matching Spark's per-row depth-1 behavior exactly.Notes
Affected
isRoot=falsenested-error-to-NULL propagation.