锋盈数科-知识库 Logo
首页
软件开发
计算机基础
Hello Halo
新手必读
关于本知识库
登录 →
锋盈数科-知识库 Logo
首页 软件开发 计算机基础 Hello Halo 新手必读 关于本知识库
登录
  1. 首页
  2. 软件开发
  3. JAVA
  4. java解析超大json文件数据

java解析超大json文件数据

0
  • JAVA
  • 发布于 2024-09-21
  • 0 次阅读
黄健
黄健

json文件大小为10G左右,对于这种超大的json使用jackson的objectmapper一把映射到java对象是不太可行的,内存一般都会溢出。此时需要使用jackson的JsonParser从文件中逐个token去读取。一般大json中都会存在某个数组中有超多的数据记录,我们需要解决的就是记录当前token路径,在读取到超大json数组时,再利用逐条数据读取mapper.readTree(jsonParser)逐条读取数据,利用数组缓存一定量的数据后,写入数据库后继续读取,知道json数组数据读取结束。

这里关键的是记录当前json的token的路径,以方便地利用mapper.readTree(jsonParser)读取任意的子节点数据。

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import sarifreport.Result;

import java.io.File;
import java.io.IOException;

public class Main {
    public static void main(String [] args){
        long start = System.currentTimeMillis();
        try {
            ObjectMapper mapper = new ObjectMapper();
            JsonFactory jsonFactory = new JsonFactory();
            JsonParser jsonParser = jsonFactory.createParser(
                    new File("E:/result2.json"));
            JsonPath path = new JsonPath();
            while (jsonParser.nextToken() != null) {
                traverse(jsonParser, 0,path,mapper);
            }
            jsonParser.close();
            System.out.println((System.currentTimeMillis()-start)/1000+"秒");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private static void traverse(JsonParser jsonParser, int depth, JsonPath path, ObjectMapper mapper) throws IOException {
        JsonToken token = jsonParser.getCurrentToken();

        if (token == null) {
            return;
        }
        setPath(jsonParser,depth,path);
        if (path.toString().equals("root.runs[i].results[i]")) {
            while (jsonParser.nextToken() == JsonToken.START_OBJECT) {
                JsonNode jsonNode = mapper.readTree(jsonParser);
                // 此处可以读取一定数量的数据后入库
                System.out.println(jsonNode.toPrettyString());
            }
            token = jsonParser.getCurrentToken();
        }
        // Recursive call for nested structures
        if (token == JsonToken.START_OBJECT || token == JsonToken.START_ARRAY) {
            while (jsonParser.nextToken() != null && jsonParser.getCurrentToken() != JsonToken.END_OBJECT
                    && jsonParser.getCurrentToken() != JsonToken.END_ARRAY) {
                traverse(jsonParser, depth + 1,path,mapper);
            }
        }
    }

    /**
     * 同一个depth只记录一个node
     * @param jsonParser
     * @param depth
     * @param path
     * @throws IOException
     */
    private static void  setPath(JsonParser jsonParser, int depth, JsonPath path) throws IOException {
        JsonToken token = jsonParser.getCurrentToken();
        if (path.nodeLink.size() > depth+1) {
            path.nodeLink.subList(depth+1,path.nodeLink.size()).clear();
        }
        JsonPath.Node prefixNode = path.nodeLink.size()>=(depth+1)?path.nodeLink.get(depth):null;
        switch (token) {
            case FIELD_NAME:
                if (prefixNode != null) {
                    prefixNode.nodeType = JsonPath.NODE_FIELD;
                    prefixNode.nodeName = jsonParser.getCurrentName();
                } else {
                    JsonPath.Node node = new JsonPath.Node();
                    node.nodeType = JsonPath.NODE_FIELD;
                    node.nodeName = jsonParser.getCurrentName();
                    path.nodeLink.add(node);
                }
                break;
            case START_ARRAY:
                if (prefixNode != null && JsonPath.NODE_FIELD.equals(prefixNode.nodeType)) {
                    prefixNode.nodeName = prefixNode.nodeName+"[i]";
                } else {
                    JsonPath.Node node = new JsonPath.Node();
                    node.nodeType = JsonPath.NODE_ARRAY;
                    path.nodeLink.add(node);
                }
                break;
            case START_OBJECT:
                if (prefixNode != null && JsonPath.NODE_FIELD.equals(prefixNode.nodeType)) {
                    prefixNode.nodeName = prefixNode.nodeName+".";
                } else {
                    JsonPath.Node node = new JsonPath.Node();
                    node.nodeType = JsonPath.NODE_OBJECT;
                    path.nodeLink.add(node);
                }
                break;
        }
    }
}
```java
import java.util.LinkedList;

public class JsonPath {
    public static String NODE_ARRAY = "array";
    public static String NODE_OBJECT = "object";
    public static String NODE_FIELD = "field";
    public LinkedList<Node> nodeLink = new LinkedList<>();

    public static class Node{
        public String nodeName;
        public String nodeType;
    }

    @Override
    public String toString() {
        if (this.nodeLink == null || nodeLink.isEmpty()) {
            return "";
        }
        StringBuilder path = new StringBuilder();
        for (int i = 0; i < nodeLink.size(); i++ ) {
            Node node = this.nodeLink.get(i);
            if (node == null) {
                continue;
            }
            if (i == 0) {
                if (NODE_ARRAY.equals(node.nodeType)) {
                    path.append("root[i]");
                } else {
                    path.append("root");
                }
            }
            if (NODE_ARRAY.equals(node.nodeType)) {
                path.append("[i]");
            }else if (NODE_OBJECT.equals(node.nodeType)) {
                path.append(".");
            } else if (NODE_FIELD.equals(node.nodeType)) {
                path.append(node.nodeName);
            }
        }
        return path.toString();
    }
}
```XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>BigJsonDeal</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>19</maven.compiler.source>
        <maven.compiler.target>19</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.16.1</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.jsonschema2pojo</groupId>
                <artifactId>jsonschema2pojo-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <sourceDirectory>${basedir}/src/main/resources/schema</sourceDirectory>
                    <targetProject>${basedir}/src/main/java</targetProject>
                    <targetPackage>com.example.types</targetPackage>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

jsonschema2pojo为一个根据json结构生成java的pojo代码的工具,对于复杂json生成pojo十分省时间。


原文链接: https://blog.csdn.net/javajingling/article/details/135774070

标签: #JAVA 991 #软件开发 1171
相关文章

Spring 实现 3 种异步接口 2024-10-18 09:07

大家好,我是苏三~ 如何处理比较耗时的接口? 这题我熟,直接上异步接口,使用 Callable、WebAsyncTask 和 DeferredResult、CompletableFuture等均可实现。 但这些方法有局限性,处理结果仅返回单个值。在某些场景下,如果需要接口异步处理的同时,还持续不断地

重学SpringBoot3-集成Redis(五)之布隆过滤器 2024-10-08 11:24

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞👍收藏⭐评论✍ 重学SpringBoot3-集成Redis(五)之布隆过滤器 1. 什么是布隆过滤器? * 基本概念 适用场景 2. 使用 Redis 实现布隆过滤器 * 项目依赖 Redis 配置

SpringBoot整合异步任务执行 2024-10-08 11:24

同步任务: 同步任务是在单线程中按顺序执行,每次只有一个任务在执行,不会引发线程安全和数据一致性等 并发问题 同步任务需要等待任务执行完成后才能执行下一个任务,无法同时处理多个任务,响应慢,影响用 户体验 异步任务: 异步任务是在多线程中同时执行,多个任务可以并发执行,同时处理多个请求,响应快,资源

springboot kafka多数据源,通过配置动态加载发送者和消费者 2024-10-08 11:24

前言 最近做项目,需要支持kafka多数据源,实际上我们也可以通过代码固定写死多套kafka集群逻辑,但是如果需要不修改代码扩展呢,因为kafka本身不处理额外逻辑,只是起到削峰,和数据的传递,那么就需要对架构做一定的设计了。 准备test kafka本身非常容易上手,如果我们需要单元测试,引入ja

SpringBoot 集成 Redis 2024-10-08 11:24

一:SpringBoot 集成 Redis ①Redis是一个 NoSQL(not only)数据库, 常作用缓存 Cache 使用。 ②Redis是一个中间件、是一个独立的服务器;常用的数据类型: string , hash ,set ,zset , list ③通过Redis客户端可以使用多种语

SpringBoot整合QQ邮箱 2024-10-08 11:24

SpringBoot可以通过导入依赖的方式集成多种技术,这当然少不了我们常用的邮箱,现在本章演示SpringBoot整合QQ邮箱发送邮件…. 下面按步骤进行: 1.获取QQ邮箱授权码 1.1 登录QQ邮箱 1.2 开启SMTP服务 找到下图中的SMTP服务区域,如果当前账号未开启的话自己手动开启。

目录

IT 外包服务商

  • 意见投递
  • zyf6619

软件开发应用

主菜单

  • 首页
  • 软件开发
  • 计算机基础
  • Hello Halo
  • 新手必读
  • 关于本知识库
Copyright © 2024 your company All Rights Reserved. Powered by Halo.