{"record":{"id":"788a72763866e0ce","repo":"apache/flink","slug":"json-format-doesn-t-support-non-string-as-key-type-788a72","errorCode":null,"errorMessage":"JSON format doesn't support non-string as key type of map. The type is: {}","messagePattern":"JSON format doesn't support non-string as key type of map\\. The type is: (.+?)","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"flink-formats/flink-json/src/main/java/org/apache/flink/formats/json/JsonToRowDataConverters.java","lineNumber":325,"sourceCode":"    private JsonToRowDataConverter createArrayConverter(ArrayType arrayType) {\n        JsonToRowDataConverter elementConverter = createConverter(arrayType.getElementType());\n        final Class<?> elementClass =\n                LogicalTypeUtils.toInternalConversionClass(arrayType.getElementType());\n        return jsonNode -> {\n            final ArrayNode node = (ArrayNode) jsonNode;\n            final Object[] array = (Object[]) Array.newInstance(elementClass, node.size());\n            for (int i = 0; i < node.size(); i++) {\n                final JsonNode innerNode = node.get(i);\n                array[i] = elementConverter.convert(innerNode);\n            }\n            return new GenericArrayData(array);\n        };\n    }\n\n    private JsonToRowDataConverter createMapConverter(\n            String typeSummary, LogicalType keyType, LogicalType valueType) {\n        if (!keyType.is(LogicalTypeFamily.CHARACTER_STRING)) {\n            throw new UnsupportedOperationException(\n                    \"JSON format doesn't support non-string as key type of map. \"\n                            + \"The type is: \"\n                            + typeSummary);\n        }\n        final JsonToRowDataConverter keyConverter = createConverter(keyType);\n        final JsonToRowDataConverter valueConverter = createConverter(valueType);\n\n        return jsonNode -> {\n            Iterator<Map.Entry<String, JsonNode>> fields = jsonNode.fields();\n            Map<Object, Object> result = new HashMap<>();\n            while (fields.hasNext()) {\n                Map.Entry<String, JsonNode> entry = fields.next();\n                Object key = keyConverter.convert(TextNode.valueOf(entry.getKey()));\n                Object value = valueConverter.convert(entry.getValue());\n                result.put(key, value);\n            }\n            return new GenericMapData(result);\n        };","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-formats/flink-json/src/main/java/org/apache/flink/formats/json/JsonToRowDataConverters.java#L307-L343","documentation":"Thrown by JsonToRowDataConverters.createMapConverter when building a converter for a MAP type whose key type is not in the CHARACTER_STRING family. JSON objects can only have string keys, so the Flink JSON deserializer refuses to build a converter for maps like MAP<INT, STRING> on the read path. This fails at converter-construction time, before any record is read.","triggerScenarios":"Table DDL or derived schema containing MAP with a non-string key (MAP<BIGINT, STRING>, MAP<INT, INT>, keys of TIMESTAMP/BOOLEAN type, etc.) used with 'format'='json' (directly or via a connector such as Kafka). It throws when JsonRowDataDeserializationSchema is instantiated, i.e. at job startup.","commonSituations":"Hand-written DDL copied from a relational schema where map keys are numeric; converting a map<bigint,...> type from another system into Flink JSON format; using the same schema for JSON and a format (like Avro-ish maps) that permits non-string keys.","solutions":["Change the map key type to STRING or VARCHAR in the DDL and cast keys in a downstream operator if numeric keys are needed","Restructure the data as an ARRAY<ROW<key K, value V>> when key order or non-string keys are required","If keys arrive as JSON strings of numbers, keep MAP<STRING, V> and parse keys in a UDF"],"exampleFix":"// before\nCREATE TABLE t (m MAP<BIGINT, STRING>) WITH ('format'='json', ...);\n\n// after\nCREATE TABLE t (m MAP<STRING, STRING>) WITH ('format'='json', ...);","handlingStrategy":"type-guard","validationCode":"LogicalType key = mapType.getKeyType();\nif (!key.is(LogicalTypeFamily.CHARACTER_STRING)) {\n    throw new IllegalArgumentException(\"JSON format requires string map keys: \" + key); // fail at plan time, not job startup\n}","typeGuard":"static boolean isJsonSafeMap(MapType t) {\n    return t.getKeyType().is(LogicalTypeFamily.CHARACTER_STRING);\n}","tryCatchPattern":null,"preventionTips":["Lint DDLs for map key types before submitting JSON-format jobs","Prefer ARRAY<ROW<key,value>> when non-string keys are needed"],"tags":["json","map","schema","deserialization","startup"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}