使用Sqoop导出HDFS JSON数据到Oracle时解析失败求助
解决Sqoop导出HDFS JSON数据到Oracle时的NumberFormatException问题
错误原因分析
你遇到的NumberFormatException核心问题是输入格式不匹配:
你的Sqoop命令配置了逗号分隔的文本输入(--input-fields-terminated-by ','),但HDFS上存储的是完整的JSON结构数据。Sqoop会把整个JSON字符串按逗号切割,比如把"DeptId":888当成一个独立的字段值,而Oracle的DeptId是Number类型,尝试将带键名的字符串转换为数字自然会触发解析失败。
解决方案1:直接使用Sqoop的JSON输入格式
修改Sqoop命令,移除逗号分隔配置,改用JSON专用的输入格式,同时明确字段类型映射:
sqoop export \ --connect "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=wcx2-scan. .com)(PORT= ))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=***)))" \ --table API.CUSTOMER \ --columns 'Id','DeptId','Strategy','RCM_PROD_MSG_TXT' \ --export-dir /tmp/test \ --input-format org.apache.hadoop.mapreduce.lib.input.JsonInputFormat \ --map-column-java Id=String,DeptId=Integer,Strategy=String,RCM_PROD_MSG_TXT=String \ --map-column-oracle DeptId=NUMBER \ --username ********* \ --password ********** \ --input-null-string '\N' \ --input-null-non-string '\N'
关键修改点:
- 移除
--input-fields-terminated-by ',':JSON格式不需要分隔符,Sqoop会自动识别每个JSON对象为一条记录 - 添加
--input-format org.apache.hadoop.mapreduce.lib.input.JsonInputFormat:告诉Sqoop按JSON格式解析输入数据 - 明确
--map-column-java:指定每个字段的Java类型,确保和JSON中的数据类型匹配(比如DeptId是数字,设为Integer) - 补充
--map-column-oracle:确认Java类型和Oracle字段类型的映射关系,避免类型转换偏差
解决方案2:通过Hive预处理JSON(适合复杂嵌套结构)
如果你的JSON包含嵌套字段(比如示例中的recs数组),先把数据导入Hive表提取需要的字段,再从Hive导出到Oracle会更灵活:
- 创建Hive外部表解析JSON:
CREATE EXTERNAL TABLE temp_customer ( Id STRING, DeptId INT, Strategy STRING ) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' LOCATION '/tmp/test';
注意:确保Hive环境中已安装JSON SerDe依赖(通常是
json-serdejar包)
- 从Hive导出到Oracle:
sqoop export \ --connect "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=wcx2-scan. .com)(PORT= ))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=***)))" \ --table API.CUSTOMER \ --columns 'Id','DeptId','Strategy','RCM_PROD_MSG_TXT' \ --export-dir /user/hive/warehouse/temp_customer \ --input-fields-terminated-by '\001' \ --map-column-java RCM_PROD_MSG_TXT=String \ --username ********* \ --password ********** \ --input-null-string '\N' \ --input-null-non-string '\N'
额外注意事项
- 对于Oracle表中缺失的
RCM_PROD_MSG_TXT字段,Sqoop会自动用你指定的\N填充为null,符合Oracle的null处理规则 - 测试阶段可以添加
--num-mappers 1减少并行度,方便排查单条数据的解析问题 - 如果JSON字段名和Oracle列名不一致,需要用
--map-column-java或--map-column-oracle明确映射关系
内容的提问来源于stack exchange,提问作者N9909
相关产品推荐
相关产品推荐

