All Products
Search
Document Center

Realtime Compute for Apache Flink:Kafka JSON Catalogs

Last Updated:Aug 19, 2026

After you configure a Kafka JSON Catalog, your Realtime Compute for Apache Flink jobs can directly access JSON topics in a Kafka cluster without defining a schema. This topic explains how to create, view, and delete Kafka JSON Catalogs.

Background

A Kafka JSON catalog infers the schema of a topic by automatically parsing JSON-formatted messages. This lets you access specific fields from messages in Flink SQL without declaring a schema for the Kafka table. A Kafka JSON catalog has the following features:

  • Table names in the catalog match Kafka topic names. This eliminates manual table registration with DDL statements, improving development efficiency and accuracy.

  • You can use tables from a Kafka JSON catalog directly as source tables in Flink SQL jobs.

  • You can use a Kafka JSON catalog with the CREATE TABLE AS (CTAS) statement to synchronize data during a schema change.

Limitations

  • A Kafka JSON catalog only supports topics with messages in JSON format.

  • Only Flink computing engine VVR 6.0.2 or later supports configuring Kafka JSON catalogs.

    Note

    To use Kafka JSON catalogs on VVR 4.x, upgrade your jobs to VVR 6.0.2 or later.

  • You cannot use DDL statements to modify an existing Kafka JSON catalog.

  • You can only query data tables. You cannot create, modify, or delete databases or tables.

    Note

    In CREATE DATABASE AS SELECT (CDAS) or CREATE TABLE AS SELECT (CTAS) scenarios using a Kafka JSON catalog, topics can be created automatically.

  • A Kafka JSON catalog cannot read from or write to Kafka clusters with SSL or SASL authentication.

  • You can use tables from a Kafka JSON catalog directly as source tables in Flink SQL jobs, but not as sink tables or lookup dimension tables.

  • Because ApsaraMQ for Kafka currently does not support deleting a Group by using the same interface as open-source Kafka, you must specify aliyun.kafka.instanceId, aliyun.kafka.accessKeyId, aliyun.kafka.accessKeySecret, aliyun.kafka.endpoint, and aliyun.kafka.regionId when you create a Kafka JSON catalog to enable automatic deletion of the Group ID. For more information, see Comparison with open-source Kafka.

Usage notes

The Kafka JSON Catalog infers a table's schema by parsing sample data. When a topic contains inconsistent data formats, the catalog keeps all columns by default and returns the widest schema. Changes to the data format in the topic can alter the inferred schema, which may cause job failures on restart.

For example, when restarting a Flink SQL job that reads from a Kafka JSON Catalog table from a savepoint, the catalog might infer a new schema that differs from the previous one. The job's execution plan is based on the old schema, which can cause runtime errors such as mismatched filter conditions or incorrect field access. To prevent these issues, use the CREATE TEMPORARY TABLE statement in your Flink SQL job to define a Kafka table with a fixed schema.

Create a Kafka JSON catalog

  1. On the Scripts page, enter the statement to create a Kafka JSON catalog in the SQL editor.

    • For a self-managed Kafka cluster or an EMR on ECS Kafka cluster

      CREATE CATALOG <YourCatalogName> WITH(
       'type'='kafka',
       'properties.bootstrap.servers'='<brokers>',
       'format'='json',
       'default-database'='<dbName>',
       'key.fields-prefix'='<keyPrefix>',
       'value.fields-prefix'='<valuePrefix>',
       'timestamp-format.standard'='<timestampFormat>',
       'infer-schema.flatten-nested-columns.enable'='<flattenNestedColumns>',
       'infer-schema.primitive-as-string'='<primitiveAsString>',
       'infer-schema.parse-key-error.field-name'='<parseKeyErrorFieldName>',
       'infer-schema.compacted-topic-as-upsert-table'='true',
       'max.fetch.records'='100'
      );
    • For ApsaraMQ for Kafka

      CREATE CATALOG <YourCatalogName> WITH(
       'type'='kafka',
       'properties.bootstrap.servers'='<brokers>',
       'format'='json',
       'default-database'='<dbName>',
       'key.fields-prefix'='<keyPrefix>',
       'value.fields-prefix'='<valuePrefix>',
       'timestamp-format.standard'='<timestampFormat>',
       'infer-schema.flatten-nested-columns.enable'='<flattenNestedColumns>',
       'infer-schema.primitive-as-string'='<primitiveAsString>',
       'infer-schema.parse-key-error.field-name'='<parseKeyErrorFieldName>',
       'infer-schema.compacted-topic-as-upsert-table'='true',
       'max.fetch.records'='100',
       'aliyun.kafka.accessKeyId'='<aliyunAccessKeyId>',
       'aliyun.kafka.accessKeySecret'='<aliyunAccessKeySecret>',
       'aliyun.kafka.instanceId'='<aliyunKafkaInstanceId>',
       'aliyun.kafka.endpoint'='<aliyunKafkaEndpoint>',
       'aliyun.kafka.regionId'='<aliyunKafkaRegionId>'
      );

    Parameter

    Type

    Description

    Required

    Remarks

    YourCatalogName

    String

    The name of the Kafka JSON catalog.

    Yes

    Specify a custom name.

    Important

    Replace the placeholder with your catalog name and remove the angle brackets (<>) to prevent a syntax error.

    type

    String

    The type of the catalog.

    Yes

    The value must be 'kafka'.

    properties.bootstrap.servers

    String

    The Kafka broker addresses.

    Yes

    Specify one or more addresses in the host1:port1,host2:port2,host3:port3 format.

    Separate multiple addresses with commas (,).

    format

    String

    The Kafka message format.

    Yes

    Currently, only 'json' is supported. Flink parses JSON-formatted messages to infer the schema.

    default-database

    String

    The default database name for the catalog.

    No

    Catalogs use a three-part identifier to locate tables: catalog_name.db_name.table_name. This parameter sets the db_name. Since Kafka does not have databases, you can use any string to represent the cluster.

    key.fields-prefix

    String

    A custom prefix added to the names of fields parsed from the message key to prevent naming conflicts.

    No

    The default value is 'key_'. For example, if a field in the key is named 'a', its name in the table schema becomes 'key_a'.

    Note

    The value of key.fields-prefix cannot be a prefix of the value of value.fields-prefix. For example, if value.fields-prefix is set to 'test1_value_', you cannot set key.fields-prefix to 'test1_'.

    value.fields-prefix

    String

    A custom prefix added to the names of fields parsed from the message value to prevent naming conflicts.

    No

    The default value is 'value_'. For example, if a field in the value is named 'b', its name in the table schema becomes 'value_b'.

    Note

    The value of value.fields-prefix cannot be a prefix of the value of key.fields-prefix. For example, if key.fields-prefix is set to 'test2_value_', you cannot set value.fields-prefix to 'test2_'.

    timestamp-format.standard

    String

    The format for parsing timestamp fields in JSON messages. Flink first attempts to parse timestamps using this format. If parsing fails, it automatically tries other standard formats.

    No

    Valid values:

    • SQL (default)

    • ISO-8601

    infer-schema.flatten-nested-columns.enable

    Boolean

    Specifies whether to recursively expand nested columns in the JSON message value.

    No

    Valid values:

    • true: Recursively expands nested columns.

      For expanded columns, Flink uses the access path as the column name. For example, for a column 'col' in {"nested": {"col": true}}, the expanded column name is 'nested.col'.

      Note

      If this parameter is set to true, we recommend that you use it with the CREATE TABLE AS (CTAS) statement. Other DML statements do not support automatic expansion of nested columns.

    • false (default): Treats nested types as STRING.

    infer-schema.primitive-as-string

    Boolean

    Specifies whether to infer all primitive types in the JSON message value as STRING.

    No

    Valid values:

    • true: Infers all primitive types as STRING.

    • false (default): Infers types based on standard rules.

    infer-schema.parse-key-error.field-name

    String

    If a non-empty message key cannot be parsed as JSON, Flink adds a VARBINARY field to the schema to hold the raw key data. The name of this new field is a combination of the key.fields-prefix and this parameter's value.

    No

    The default value is 'col'. For example, if the message value parses into a field named 'value_name' and the message key is not empty but fails to be parsed, the resulting schema contains two fields: 'key_col' and 'value_name'.

    infer-schema.compacted-topic-as-upsert-table

    Boolean

    Specifies whether to treat the topic as an Upsert Kafka table. This applies only when the topic's cleanup policy is 'compact' and the message key is not empty.

    No

    The default value is true. This parameter must be set to true when you use CTAS or CDAS statements to synchronize data to an ApsaraMQ for Kafka instance.

    Note

    This parameter is supported only in VVR 6.0.2 and later.

    max.fetch.records

    Int

    The maximum number of messages to sample for schema inference.

    No

    The default value is 100.

    aliyun.kafka.accessKeyId

    String

    The AccessKey ID of your Alibaba Cloud account. For more information, see Create an AccessKey pair.

    No

    This parameter is required when you use CTAS or CDAS statements to synchronize data to an ApsaraMQ for Kafka instance.

    Note

    This parameter is supported only in VVR 6.0.2 and later.

    aliyun.kafka.accessKeySecret

    String

    The AccessKey Secret of your Alibaba Cloud account. For more information, see Create an AccessKey pair.

    No

    This parameter is required when you use CTAS or CDAS statements to synchronize data to an ApsaraMQ for Kafka instance.

    Note

    This parameter is supported only in VVR 6.0.2 and later.

    aliyun.kafka.instanceId

    String

    The instance ID of the ApsaraMQ for Kafka instance. You can view the instance ID on the instance details page in the ApsaraMQ for Kafka console.

    No

    This parameter is required when you use CTAS or CDAS statements to synchronize data to an ApsaraMQ for Kafka instance.

    Note

    This parameter is supported only in VVR 6.0.2 and later.

    aliyun.kafka.endpoint

    String

    The API endpoint for ApsaraMQ for Kafka. For more information, see Endpoints.

    No

    This parameter is required when you use CTAS or CDAS statements to synchronize data to an ApsaraMQ for Kafka instance.

    Note

    This parameter is supported only in VVR 6.0.2 and later.

    aliyun.kafka.regionId

    String

    The Region ID of the instance where the topic resides. For more information, see Endpoints.

    No

    This parameter is required when you use CTAS or CDAS statements to synchronize data to an ApsaraMQ for Kafka instance.

    Note

    This parameter is supported only in VVR 6.0.2 and later.

  2. Select the CREATE CATALOG statement, and then click Run in the left-side gutter.

    CREATE CATALOG KafkaCatalog WITH(
    'type'='kafka',
    'properties.bootstrap.servers'='<brokers>',
    'format'='json',
    'default-database'='<dbName>',
    'key.fields-prefix'='<keyPrefix>',
    'value.fields-prefix'='<valuePrefix>',
    'timestamp-format.standard'='<timestampFormat>',
    'infer-schema.flatten-nested-columns.enable'='<flattenNestedColumns>',
    'infer-schema.primitive-as-string'='<primitiveAsString>',
    'infer-schema.parse-key-error.field-name'='<parseKeyErrorFieldName>',
    'infer-schema.compacted-topic-as-upsert-table'='true',
    'max.fetch.records'='100',
    'aliyun.kafka.accessKeyId'='<aliyunAccessKeyId>',
    'aliyun.kafka.accessKeySecret'='<aliyunAccessKeySecret>',
    'aliyun.kafka.instanceId'='<aliyunKafkaInstanceId>',
    'aliyun.kafka.endpoint'='<aliyunKafkaEndpoint>',
    'aliyun.kafka.regionId'='<aliyunKafkaRegionId>'
    );
  3. Verify that the catalog appears in the Catalogs area on the left.

Kafka JSON catalog

  1. Enter the following command in the Scripts editor.

    DESCRIBE `${catalog_name}`.`${db_name}`.`${topic_name}`;

    Parameter

    Description

    ${catalog_name}

    The name of the Kafka JSON catalog.

    ${db_name}

    The name of the Kafka cluster.

    ${topic_name}

    The name of the Kafka topic.

  2. Select the DESCRIBE statement, and then click Run in the left-side gutter.

    After the statement runs successfully, the results pane displays the field definitions for the Kafka source table. The output includes the business fields value_from (STRING), value_name (STRING), and value_order (BIGINT), and the metadata virtual fields partition (INT, primary key), offset (BIGINT, primary key), and timestamp (TIMESTAMP_LTZ(3)). For these metadata virtual fields, the extras column shows METADATA VIRTUAL.

Use a Kafka JSON catalog

  • As a source table to read data from a Kafka topic.

    INSERT INTO ${other_sink_table}
    SELECT...
    FROM `${kafka_catalog}`.`${db_name}`.`${topic_name}`/*+OPTIONS('scan.startup.mode'='earliest-offset')*/;
    Note

    To specify additional WITH options for a table in the Kafka JSON catalog, use SQL hints. For example, the preceding SQL statement uses a hint to start consuming data from the earliest offset. For more information about other parameters, see ApsaraMQ for Kafka source table parameters and ApsaraMQ for Kafka sink table parameters.

  • As a source table with a CREATE TABLE AS (CTAS) statement to synchronize data from a Kafka topic to a destination table.

    • Synchronize a single table in real time.

      CREATE TABLE IF NOT EXISTS `${target_table_name}`
      WITH(...)
      AS TABLE `${kafka_catalog}`.`${db_name}`.`${topic_name}`
      /*+OPTIONS('scan.startup.mode'='earliest-offset')*/;
    • Synchronize multiple tables in a single job.

      BEGIN STATEMENT SET;
      CREATE TABLE IF NOT EXISTS `some_catalog`.`some_database`.`some_table0`
      AS TABLE `kafka-catalog`.`kafka`.`topic0`
      /*+ OPTIONS('scan.startup.mode'='earliest-offset') */;
      CREATE TABLE IF NOT EXISTS `some_catalog`.`some_database`.`some_table1`
      AS TABLE `kafka-catalog`.`kafka`.`topic1`
      /*+ OPTIONS('scan.startup.mode'='earliest-offset') */;
      CREATE TABLE IF NOT EXISTS `some_catalog`.`some_database`.`some_table2`
      AS TABLE `kafka-catalog`.`kafka`.`topic2`
      /*+ OPTIONS('scan.startup.mode'='earliest-offset') */;
      END;

      With a Kafka JSON catalog, you can synchronize multiple Kafka tables in the same job. The following conditions apply:

      • None of the Kafka tables are configured with the topic-pattern parameter.

      • The Kafka configuration for each table must be identical, including all properties.* settings such as properties.bootstrap.servers and properties.group.id.

      • The scan.startup.mode setting for each table must be identical and can only be set to group-offsets, latest-offset, or earliest-offset.

      For example, in the following figure, the top two tables meet the conditions, while the bottom two tables violate them.示例

Note

For end-to-end examples of using a Kafka JSON catalog, see real-time log warehousing.

Delete a Kafka JSON catalog

Warning

Deleting a Kafka JSON catalog does not affect running jobs. However, a job using a table from the catalog will fail with a "table not found" error if you deploy or restart it. Proceed with caution.

  1. Enter the following command in the SQL editor on the Scripts page.

    DROP CATALOG ${catalog_name};

    Replace ${catalog_name} with the name of your Kafka JSON catalog.

  2. Select the DROP CATALOG command, right-click, and select Run.

  3. Verify that the catalog is no longer listed in the Catalogs area on the left.

Kafka JSON Catalog tables

To simplify using tables from a Kafka JSON Catalog, the catalog automatically adds default configuration parameters, metadata, and primary key information to the inferred tables.

  • Schema inference for Kafka tables

    When inferring the schema for a topic, the Kafka JSON Catalog samples up to max.fetch.records messages. It parses the schema of each message and then merges these individual schemas into a final schema. The parsing rules are the same as the basic rules used when Kafka is a data source for a CREATE TABLE AS (CTAS) statement.

    Important
    • During schema inference, the Kafka JSON Catalog creates a consumer group to read data from the topic. The catalog prefixes the consumer group name to indicate it was created by the catalog.

    • For ApsaraMQ for Kafka, we recommend using the Kafka JSON Catalog with version 6.0.7 or later. Versions prior to 6.0.7 do not automatically delete the consumer group, which can cause alerts about message backlogs.

    • Inferred physical columns

      The Kafka JSON Catalog infers physical columns from the message key and message value.

      If the message key is not empty but cannot be parsed, the catalog returns a VARBINARY column. The name of this column is a concatenation of the value of the key.fields-prefix parameter and the value of the infer-schema.parse-key-error.field-name parameter.

      After fetching a batch of Kafka messages, the catalog parses each message and merges the resulting physical columns into a unified schema for the topic.

      • If the inferred physical columns contain fields not in the result schema, the catalog automatically adds them to the result schema.

        • If the types are the same but the precision is different, the type with the higher precision is used.

        • If the types are different, the system finds their lowest common parent in the type tree (shown in the figure below) and uses that as the column's type. However, to preserve precision, when a Decimal and a Float type are merged, the resulting type is Double.Schema合并

      For example, for a Kafka topic that contains the following three messages, the Kafka JSON Catalog infers the schema as shown in the figure below.Schema

    • Default metadata columns

      By default, the Kafka JSON Catalog adds three metadata columns: partition, offset, and timestamp.

      Metadata name

      Column name

      Type

      Description

      partition

      partition

      INT NOT NULL

      The partition ID.

      offset

      offset

      BIGINT NOT NULL

      The message offset.

      timestamp

      timestamp

      TIMESTAMP_LTZ(3) NOT NULL

      The message timestamp.

    • Default primary key constraint

      When a table from a Kafka JSON Catalog is used as a source, the metadata columns partition and offset serve as the default primary key to ensure data uniqueness.

    Note

    If the schema inferred by the Kafka JSON Catalog does not meet your requirements, you can declare a temporary table with your desired schema using the CREATE TEMPORARY TABLE ... LIKE syntax. For example, if your JSON data contains a ts field with the format '2023-01-01 12:00:01', the Kafka JSON Catalog automatically infers the ts field as a TIMESTAMP type. To use the ts field as a STRING type, declare the table as follows. Because the default configuration adds the value_ prefix to fields from the message value, the field name here is value_ts.

    CREATE TEMPORARY TABLE tempTable (
        value_name STRING,
        value_ts STRING
    ) LIKE `kafkaJsonCatalog`.`kafka`.`testTopic`;
  • Default table parameters

    Parameter

    Description

    Remarks

    connector

    The connector type.

    The value is kafka or upsert-kafka.

    topic

    The name of the corresponding topic.

    This is the same as the declared table name.

    properties.bootstrap.servers

    The Kafka broker addresses.

    Same as the catalog's properties.bootstrap.servers setting.

    value.format

    The format used by the Flink Kafka connector to serialize or deserialize the Kafka message value.

    The value is json.

    value.fields-prefix

    Specifies a custom prefix for all fields from the Kafka message value to avoid naming conflicts with fields from the message key or metadata.

    Same as the catalog's value.fields-prefix setting.

    value.json.infer-schema.flatten-nested-columns.enable

    Specifies whether to recursively expand nested columns in the JSON of the message value.

    Same as the catalog's infer-schema.flatten-nested-columns.enable setting.

    value.json.infer-schema.primitive-as-string

    Specifies whether to infer all primitive types in the message value as the STRING type.

    Same as the catalog's infer-schema.primitive-as-string setting.

    value.fields-include

    Defines how the message value handles fields from the message key.

    The value is EXCEPT_KEY, which means the message value does not include fields from the message key.

    This parameter is configured only if the message key is not empty.

    key.format

    The format used by the Flink Kafka connector to serialize or deserialize the Kafka message key.

    The value is json or raw.

    This parameter is configured only if the message key is not empty.

    When the message key is not empty but parsing fails, the value is raw. If parsing is successful, the value is json.

    key.fields-prefix

    Specifies a custom prefix for all fields from the Kafka message key to avoid naming conflicts with fields from the message value.

    Same as the catalog's key.fields-prefix setting.

    This parameter is configured only if the message key is not empty.

    key.fields

    The fields that store data parsed from the Kafka message key.

    The list of parsed key fields is automatically populated.

    This parameter is configured only if the message key is not empty and the table is not an Upsert Kafka table.