Skip to content

Data Engineer Associate · Domain 2: Data Ingestion and Loading · 21% of the exam

Task 2.7: Ingest semi-structured and unstructured data (for example, JSON and nested data) via Lakeflow Connect and other managed connectors into Unity Catalog–governed Delta tables.

JSON options such as multiLine, VARIANT and parse_json, querying nested fields, from_json and explode, and landing documents and binary files from file connectors and volumes.

Study it

  • JSON, nested data and VARIANT; unstructured files

    Lesson coming

Sample questions

Try each one before opening the answer. Every option is explained, with the Databricks documentation page that proves it.

Question 1 · choose 1

A bronze table stores each event as a JSON document in the STRING column payload. The silver table should keep the whole document in a VARIANT column so new or nested fields remain queryable without a fixed schema. Which function converts payload to VARIANT?

  1. Afrom_json(payload, schema)
  2. Bto_json(payload)
  3. Cschema_of_json(payload)
  4. Dparse_json(payload)
Show the answer and why
  • Afrom_json(payload, schema)

    Incorrect

    from_json parses the string into a STRUCT that matches a schema you supply, which is the fixed schema the team wants to avoid.

  • Bto_json(payload)

    Incorrect

    to_json goes the other way: it turns a struct or VARIANT value into a JSON string.

  • Cschema_of_json(payload)

    Incorrect

    schema_of_json returns a DDL schema string describing the JSON; it does not convert the data.

  • Dparse_json(payload)

    Correct

    parse_json takes a JSON string and returns the equivalent VARIANT value, which keeps the full document and its nesting.

VARIANT stores semi-structured data flexibly, and parse_json is the function that produces it from a JSON string. from_json is for parsing into a known struct schema.

Question 2 · choose 1

Each source file contains a single pretty-printed JSON object that spans many lines. spark.read.format("json").load(path) returns one _corrupt_record column instead of the fields. Which reader option fixes this?

  1. Amode set to DROPMALFORMED
  2. BmultiLine set to true
  3. CprimitivesAsString set to true
  4. DallowComments set to true
Show the answer and why
  • Amode set to DROPMALFORMED

    Incorrect

    DROPMALFORMED discards corrupted records, so the data would be dropped instead of read.

  • BmultiLine set to true

    Correct

    By default each line must be a complete JSON record; multiLine lets one record span multiple lines.

  • CprimitivesAsString set to true

    Incorrect

    This infers all primitive values as strings; it does not change how records are split.

  • DallowComments set to true

    Incorrect

    This ignores Java and C++ style comments in JSON; the problem here is records spanning lines.

The JSON reader expects JSON Lines by default. Files with one object across many lines need multiLine.

Question 3 · choose 1

The bronze table store_data has a STRING column raw that holds JSON documents. Without defining a schema, an analyst needs the nested value at store.bicycle.color. Which expression returns it?

  1. Araw.store.bicycle.color
  2. Bvariant_get(raw, '$.store.bicycle.color', 'string')
  3. Cexplode(raw)
  4. Draw:store.bicycle.color
Show the answer and why
  • Araw.store.bicycle.color

    Incorrect

    Dot notation navigates STRUCT columns; raw is a string, so there are no fields to navigate.

  • Bvariant_get(raw, '$.store.bicycle.color', 'string')

    Incorrect

    variant_get takes a VARIANT expression; raw is a STRING column.

  • Cexplode(raw)

    Incorrect

    explode turns an array or map into rows; it does not extract a field from a JSON string.

  • Draw:store.bicycle.color

    Correct

    For JSON strings, the column:path syntax extracts a field, and dot notation after the colon reaches nested fields.

Databricks SQL can query JSON strings directly with column:path syntax; the results are strings. For better read performance, extract frequently used fields into typed columns.

Question 4 · choose 1

An Auto Loader stream ingests JSON records whose structure changes often. The team wants each record stored whole in one VARIANT column, so no schema evolution is needed during ingestion. Which option should they set?

  1. A.option("singleVariantColumn", "data")
  2. B.option("cloudFiles.schemaEvolutionMode", "rescue")
  3. C.option("cloudFiles.inferColumnTypes", "true")
  4. D.option("cloudFiles.format", "binaryFile")
Show the answer and why
  • A.option("singleVariantColumn", "data")

    Correct

    This loads each record as a single VARIANT column; because the whole record is one value, no schema evolution occurs during ingestion.

  • B.option("cloudFiles.schemaEvolutionMode", "rescue")

    Incorrect

    Rescue mode keeps a fixed column schema and puts unexpected fields in the rescued data column; the record is still split into columns.

  • C.option("cloudFiles.inferColumnTypes", "true")

    Incorrect

    This makes inference choose types for each column; records are still split into columns that can evolve.

  • D.option("cloudFiles.format", "binaryFile")

    Incorrect

    binaryFile loads raw file bytes and metadata, so the JSON fields would not be queryable.

Landing whole records as VARIANT makes ingestion robust to schema drift. Malformed records and records over 16 MB cannot be stored as VARIANT.

Question 5 · choose 1

XML files in /Volumes/main/landing/books are shaped like <catalog><book id="1"><title>...</title><price>...</price></book><book id="2">...</book></catalog>. A bronze table needs one row per book, with the fields of each book as columns. Which query reads them that way?

  1. ASELECT * FROM read_files('/Volumes/main/landing/books', format => 'xml', rowTag => 'catalog')
  2. BSELECT * FROM read_files('/Volumes/main/landing/books', format => 'xml', rootTag => 'book')
  3. CSELECT * FROM read_files('/Volumes/main/landing/books', format => 'xml', rowTag => 'book')
  4. DSELECT * FROM read_files('/Volumes/main/landing/books', format => 'xml')
Show the answer and why
  • ASELECT * FROM read_files('/Volumes/main/landing/books', format => 'xml', rowTag => 'catalog')

    Incorrect

    The rowTag element becomes the row, so with catalog as the row tag the whole file is one row that holds an array of book structs.

  • BSELECT * FROM read_files('/Volumes/main/landing/books', format => 'xml', rootTag => 'book')

    Incorrect

    rootTag is a writer option for the root element that wraps the row elements in XML output; reading XML needs rowTag.

  • CSELECT * FROM read_files('/Volumes/main/landing/books', format => 'xml', rowTag => 'book')

    Correct

    rowTag names the XML element that maps to a row; with book as the row tag, each book becomes a row and its child elements and attributes become its fields.

  • DSELECT * FROM read_files('/Volumes/main/landing/books', format => 'xml')

    Incorrect

    rowTag is a required option for reading XML; without it the reader does not know which element maps to a row.

XML does not map to rows by itself, so the XML reader needs the rowTag option: the element it names becomes the top-level struct of each row, and its child elements become the fields. Databricks reads XML natively with read_files, Auto Loader and COPY INTO.

Practise domain 2 →Practise all domains →