You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust报错‘EOF while parsing an object’问题排查求助

Rust读取JSON插入MySQL解析panic问题解决

问题场景

以下是一段用于读取JSON文件并将数据插入MySQL的Rust代码:

use std::fs::File;
use std::io::{prelude::*, BufReader};
use serde_json::{Value};

use mysql::*;
use mysql::prelude::*;

struct Show {
    title: String,
    show_poster: String,
    show_url: String,
}

fn main() {
    // Open and read the file lines
    let path = r"C:\Users\egete\Desktop\projects\cdeneme\rust\mysqljson\src\info.json";
    let file = File::open(path).expect("Unable to read file");
    let reader = BufReader::new(file);
    let lines: Vec<String> = reader.lines().map(|l| l.expect("Could not parse line")).collect();

    // Connect to your my-sql database
    let url = Opts::from_url("mysql://root:Egetelli99@localhost:3306/jsonmysql").unwrap();
    let pool = Pool::new(url).unwrap();
    let mut conn = pool.get_conn().unwrap();

    // Loop through the lines
    for line in lines {

        // Parse the line into a JSON object serde_json::Value
        let v: Value = serde_json::from_str(&line).expect("Unable to parse");

        // Since we want to save the streaming services of the said show, we need to 
        // loop an array inside the JSON file.
        let l = v["watchAvailability"][0]["directUrls"].as_array().unwrap().len();
        for n in 0..l {
            let streaming_url = v["watchAvailability"][0]["directUrls"][n].as_str().clone();
            match streaming_url {
                Some(url) => {
                    // Display the streaming url.  I have to do this to remove the Some(url) warning. 
                    // Unused variables in Rust emits warnings
                    println!("{:?}", url);

                    // Create a vector (array of object).  
                    // This provides you the ability to process multiple objects upon saving
                    let shows = vec![
                        Show { 
                            title: v["title"].as_str().as_deref().unwrap_or("Error").to_string(),
                            show_poster: v["posterPath"].as_str().as_deref().unwrap_or("Error").to_string(),
                            show_url: v["watchAvailability"][0]["directUrls"][n].as_str().as_deref().unwrap_or("Error").to_string(),
                        },
                    ];  
                    //Execute an insert query
                    conn.exec_batch(
                        r"INSERT INTO `shows` (`title`, `show_poster`, `show_url`)
                        VALUES (:title, :show_poster, :show_url)",
                    shows.iter().map(|s| params! {
                        "title" => s.title.clone(),
                        "show_poster" => s.show_poster.clone(),
                        "show_url" => s.show_url.clone(),
                        })
                    ).unwrap_err();
                },
                _ => println!("Error"),
            }
        }

    }
}

运行时触发panic,错误信息:

thread 'main' panicked at 'Unable to parse: Error("EOF while parsing an object", line: 1, column: 1)', src\main.rs:30:52
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\mysqljson.exe` (exit code: 101)

错误原因

  1. JSON读取方式错误:代码按行读取文件后尝试将每行单独解析为JSON对象,但你的info.json应该是单个完整的JSON结构(比如一个对象或数组),而非每行一个独立JSON的JSON Lines格式。单独读取第一行(比如仅{或数组开头)时,解析器会因JSON不完整触发EOF错误。
  2. 数据库执行逻辑错误:conn.exec_batch调用了unwrap_err(),这会强制在SQL执行成功时panic(unwrap_err()仅接受错误结果,成功时会触发panic)。
  3. unwrap滥用:多处使用unwrap(),一旦JSON结构不符合预期会直接panic,代码鲁棒性差。

解决方法

1. 读取整个JSON文件内容

放弃按行读取,直接读取整个文件的字符串内容,再一次性解析成JSON结构。

2. 修正数据库执行的错误处理

将unwrap_err()改为unwrap(),或使用match/if let处理执行结果,避免不必要的panic。

3. 优化JSON取值逻辑

使用更安全的方式获取JSON字段,减少unwrap()的使用,避免因结构变化导致的panic。

修改后的完整代码

use std::fs::read_to_string;
use serde_json::Value;

use mysql::{params, Opts, Pool};
use mysql::prelude::*;

struct Show {
    title: String,
    show_poster: String,
    show_url: String,
}

fn main() {
    // 读取整个JSON文件内容
    let path = r"C:\Users\egete\Desktop\projects\cdeneme\rust\mysqljson\src\info.json";
    let json_content = read_to_string(path).expect("无法读取文件");
    
    // 解析整个JSON结构
    let v: Value = serde_json::from_str(&json_content).expect("无法解析JSON");

    // 连接MySQL数据库
    let url = Opts::from_url("mysql://root:Egetelli99@localhost:3306/jsonmysql").unwrap();
    let pool = Pool::new(url).unwrap();
    let mut conn = pool.get_conn().unwrap();

    // 处理watchAvailability中的directUrls
    if let Some(watch_list) = v["watchAvailability"].as_array() {
        for watch_item in watch_list {
            if let Some(direct_urls) = watch_item["directUrls"].as_array() {
                let title = v["title"].as_str().unwrap_or("Error").to_string();
                let show_poster = v["posterPath"].as_str().unwrap_or("Error").to_string();
                
                // 批量准备数据
                let shows: Vec<Show> = direct_urls.iter()
                    .filter_map(|url_val| url_val.as_str())
                    .map(|url| Show {
                        title: title.clone(),
                        show_poster: show_poster.clone(),
                        show_url: url.to_string(),
                    })
                    .collect();

                // 执行批量插入
                if !shows.is_empty() {
                    match conn.exec_batch(
                        r"INSERT INTO `shows` (`title`, `show_poster`, `show_url`)
                        VALUES (:title, :show_poster, :show_url)",
                        shows.iter().map(|s| params! {
                            "title" => &s.title,
                            "show_poster" => &s.show_poster,
                            "show_url" => &s.show_url,
                        })
                    ) {
                        Ok(_) => println!("批量插入成功"),
                        Err(e) => eprintln!("插入失败: {}", e),
                    }
                }
            }
        }
    }
}

额外说明

  • 如果你的JSON文件确实是每行一个独立JSON(JSON Lines格式),则需要检查文件中是否有空行,或者每行的JSON是否完整,空行解析时会触发EOF错误。
  • 实际生产环境中,建议替换所有unwrap()为match或?操作符(需要将main改为Result<(), Box<dyn std::error::Error>>),提升代码鲁棒性。

内容的提问来源于stack exchange,提问作者Ege Telli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 23:36:16