Seatunnel解决ftp读取json文件无法读取数组以及格式化之后的json无法解析的问题

问题原因

在JsonRead这个方法里面 在源码中使用的逻辑是读取一行 然后把这个json进行解析

但是这样存在一个问题 比如如果json的格式是这样的

{

name:"zhangsan",

age:25

}

如果是这样的话 第一行读到的内容就是 {

显然 一个 { 并不是一个json 这样会导致解析json失败

问题解决的思路

我的方法是将整个文件中的内容全部解析

然后使用Seatunnel中自带的JackJson这个工具类进行解析

然后再获取到单个的Json对象 之后再解析成一个Json的字符串

因为解析过之后的Json字符串肯定不存在换行 所以这种换行的问题算是规避了

但是这样又引发了另一个问题就是 一下子加载全部的文件内容可能会导致内存飙升 而且解析json 构造对象这个过程也是比较耗费资源的

但是我目前没有想出来更好的方法

我目前的业务需求是 这种ftp的文件都是小文件 不存在特别大的json 所以我的这个方法是可以完成现在的需求的

修改代码的内容

要修改的代码的位置是

org/apache/seatunnel/connectors/seatunnel/file/source/reader/JsonReadStrategy.java

java 复制代码
    @Override
    public void readProcess(
            String path,
            String tableId,
            Collector<SeaTunnelRow> output,
            InputStream inputStream,
            Map<String, String> partitionsMap,
            String currentFileName)
            throws IOException {
        InputStream actualInputStream;
        switch (compressFormat) {
            case LZO:
                LzopCodec lzo = new LzopCodec();
                actualInputStream = lzo.createInputStream(inputStream);
                break;
            case NONE:
                actualInputStream = inputStream;
                break;
            default:
                log.warn(
                        "Json file does not support this compress type: {}",
                        compressFormat.getCompressCodec());
                actualInputStream = inputStream;
                break;
        }
        try (BufferedReader reader =
                new BufferedReader(new InputStreamReader(actualInputStream, encoding))) {
            //TODO wxt 优先使用之前的方法
            try{
                reader.lines()
                        .forEach(
                                line -> {
                                    try {
                                        SeaTunnelRow seaTunnelRow =
                                                deserializationSchema.deserialize(
                                                        line.getBytes(StandardCharsets.UTF_8));
                                        if (isMergePartition) {
                                            int index = seaTunnelRowType.getTotalFields();
                                            for (String value : partitionsMap.values()) {
                                                seaTunnelRow.setField(index++, value);
                                            }
                                        }
                                        seaTunnelRow.setTableId(tableId);
                                        output.collect(seaTunnelRow);
                                    } catch (IOException e) {
                                        String errorMsg =
                                                String.format(
                                                        "Deserialize this jsonFile data [%s] failed, please check the origin data",
                                                        line);
                                        throw new FileConnectorException(
                                                FileConnectorErrorCode.DATA_DESERIALIZE_FAILED,
                                                errorMsg,
                                                e);
                                    }
                                });
            }catch (Exception e){
                //region 我修改的内容

                //首先读取全部的内容
                // 将 BufferedReader 内容读取到一个 String
                StringWriter stringWriter = new StringWriter();
                String line;
                while ((line = reader.readLine()) != null) {
                    stringWriter.write(line);
                }
                String jsonContent = stringWriter.toString();

                // 判断 JSON 类型并处理
                ObjectMapper objectMapper = new ObjectMapper();
                JsonNode jsonNode = objectMapper.readTree(jsonContent);

                if (jsonNode.isArray()) {
                 
                    // 遍历数组并转换为单行字符串
                    for (JsonNode node : jsonNode) {
                        String singleLineJson = objectMapper.writeValueAsString(node);
                       // region 这一部分是我直接从上面复制下来的
                        try {
                            SeaTunnelRow seaTunnelRow =
                                    deserializationSchema.deserialize(
                                            singleLineJson.getBytes(StandardCharsets.UTF_8));
                            if (isMergePartition) {
                                int index = seaTunnelRowType.getTotalFields();
                                for (String value : partitionsMap.values()) {
                                    seaTunnelRow.setField(index++, value);
                                }
                            }
                            seaTunnelRow.setTableId(tableId);
                            output.collect(seaTunnelRow);
                        } catch (IOException e1) {
                            String errorMsg =
                                    String.format(
                                            "Deserialize this jsonFile data [%s] failed, please check the origin data",
                                            singleLineJson);
                            throw new FileConnectorException(
                                    FileConnectorErrorCode.DATA_DESERIALIZE_FAILED,
                                    errorMsg,
                                    e);
                        }
                        // endregion
                    }
                } else if (jsonNode.isObject()) {
                    String singleLineJson = objectMapper.writeValueAsString(jsonNode);
                    // region 这一部分是我直接从上面复制下来的
                    try {
                        SeaTunnelRow seaTunnelRow =
                                deserializationSchema.deserialize(
                                        singleLineJson.getBytes(StandardCharsets.UTF_8));
                        if (isMergePartition) {
                            int index = seaTunnelRowType.getTotalFields();
                            for (String value : partitionsMap.values()) {
                                seaTunnelRow.setField(index++, value);
                            }
                        }
                        seaTunnelRow.setTableId(tableId);
                        output.collect(seaTunnelRow);
                    } catch (IOException e1) {
                        String errorMsg =
                                String.format(
                                        "Deserialize this jsonFile data [%s] failed, please check the origin data",
                                        singleLineJson);
                        throw new FileConnectorException(
                                FileConnectorErrorCode.DATA_DESERIALIZE_FAILED,
                                errorMsg,
                                e);
                    }
                    // endregion
                }


                //endregion


            }



        }
    }
相关推荐
_Evan_Yao19 分钟前
Redis 缓存穿透、击穿、雪崩,一次讲清!
java·spring·mybatis
梓豪csd44 分钟前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
秋饼1 小时前
Spring AI 2.1 Message Parts 深度实战:推理签名回放与跨轮记忆持久化的源码级落地
java·ai·技术分享·后端开发
thefool1122662 小时前
TCP 1
java·1024程序员节
金銀銅鐵4 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
AI人工智能+电脑小能手4 小时前
一次请求打几个下游,这个Java并行任务工具类6个方法按序聚合
java·线程池·并发编程·1024程序员节·批量处理·并行任务
paopaokaka_luck6 小时前
心理咨询管理系统(WebSocket实时沟通、基于用户的协同过滤、 ECharts多维分析、 预约业务流程、预约校验与定时处理)
java·vue.js·spring boot·mysql·spring·echarts·1024程序员节
2301_32241428046 小时前
springboot农产品交易平台的设计与实现08055-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·spring boot·redis·mysql·tomcat·maven·mybatis
考虑考虑7 小时前
JDK26的JEP 500属性
java·后端·java ee
LMT流氓兔7 小时前
第五单元——第十二课:把脚本整理成项目
java·数据库·python·langchain·1024程序员节