如何在Rust中搜索和解析任意长的JSON文件?
所以我和一个朋友正在用Rust制作我们自己的包管理器,我们需要为它解析JSON。我们找到了,它向我们展示了如何做到这一点的基本知识,但在我们的情况下,我们正在解析的文件可以小到1个条目,也可以大到1000个(或更多!)。下面是我们需要解析的JSON格式:如何在Rust中搜索和解析任意长的JSON文件?,json,rust,Json,Rust,所以我和一个朋友正在用Rust制作我们自己的包管理器,我们需要为它解析JSON。我们找到了,它向我们展示了如何做到这一点的基本知识,但在我们的情况下,我们正在解析的文件可以小到1个条目,也可以大到1000个(或更多!)。下面是我们需要解析的JSON格式: [ { "Name": "libexample", "Version": "5.0.0", "Depends": "dependency1, dependency2, dependency3", "Mai
[
{
"Name": "libexample",
"Version": "5.0.0",
"Depends": "dependency1, dependency2, dependency3",
"Maintainer": "example@example.com",
"Author": "person@author.com",
"Homepage": "www.homepage.com",
"Depiction": "package.depiction.com/file.json",
"Description": "This package contains an example!",
"State": "Stable",
"Provides": "Example",
"Replaces": "Free space on your hard drive",
"OS": "darwin, linux",
"Architecture": "amd64"
},
{
"Name": "libexample",
"Version": "6.0.0",
"Depends": "dependency1, dependency2, dependency3",
"Maintainer": "example@example.com",
"Author": "person@author.com",
"Homepage": "www.homepage.com",
"Depiction": "package.depiction.com/file.json",
"Description": "This package contains an example!",
"State": "Beta",
"Provides": "Example",
"Replaces": "Free space on your hard drive",
"OS": "darwin, linux",
"Architecture": "amd64"
},
{
"Name": "libexample",
"Version": "7.0.0",
"Depends": "dependency1, dependency2, dependency3",
"Maintainer": "example@example.com",
"Author": "person@author.com",
"Homepage": "www.homepage.com",
"Depiction": "package.depiction.com/file.json",
"Description": "This package contains an example!",
"State": "Alpha",
"Provides": "Example",
"Replaces": "Free space on your hard drive",
"OS": "darwin, linux",
"Architecture": "amd64"
},
{
"Name": "libanotherexample",
"Version": "3.8.2",
"Depends": "dependency1, dependency2, dependency3",
"Maintainer": "example@example.com",
"Author": "person@author.com",
"Homepage": "www.homepage.com",
"Depiction": "package.depiction.com/file.json",
"Description": "This package contains an example!",
"State": "Stable",
"Provides": "Another example",
"Replaces": "Free space on your hard drive",
"OS": "darwin, linux",
"Architecture": "amd64"
}
]
我们的问题是,我们不知道如何解析任意长度的文件,也不知道如何搜索它们。例如,如果有人查找包名,我们如何搜索整个文件以将其与其中一个名称条目相匹配,然后显示该包的其余信息?extern-crater-rustc\u serialize;
extern crate rustc_serialize;
extern crate serde_json;
extern crate serde;
extern crate serde_derive;
use std::fs::File;
use std::io::Read;
use std::str;
use serde_derive::Serialize;
use serde_derive::Deserialize;
#[derive(Serialize ,Deserialize)]
struct Person{
first_name: String,
last_name: String,
age: i64,
}
impl Person{
fn show(&self){
println!("First_Name:{} Last_Name:{} Age:{}",self.first_name,self.last_name,self.age);
}
}
fn main() {
let mut file = File::open("text.json").unwrap();
let mut data = Vec::new();
file.read_to_end(&mut data).unwrap();
let s = match str::from_utf8(&data) {
Ok(v) => v,
Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
};
let values: Vec<_> = s.split("},").collect();
let mut i=0;
while i<values.len(){
let mut str1=values[i].to_string();
if i==0{
str1 = str1.replace("[", "");
str1=str1+"}";
}
else if i==values.len()-1{
str1 = str1.replace("]", "");
}
else{
str1=str1.to_string()+"}";
}
let res=serde_json::from_str(&str1);
if res.is_ok(){
let p:Person=res.unwrap();
p.show();
}else{
println!("Sorry ! we could not pass json");
}
i=i+1;
}
}
/*fn main(){
let mut file = File::open("text.json").unwrap();
let data = String::new();
file.read_to_end(data).unwrap();
let res=serde_json::from_str(&data);
if res.is_ok(){
let p:Person=res.unwrap();
println!("{}",p.first_name);
println!("{}",p.age);
}
else{
println!("cannot pass the value");
}
// for i in data.iter(){
// println!("{}",i);
// }
/*let s = match str::from_utf8(&data) {
Ok(v) => v,
Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
};*/
//println!("result: {}", s);
/*let str1=String::from(s);*/
//println!("result: {}", str1);
//let main_vec= str1.lines().map(|s| s.trim().split('}').map(String::from).collect::<Vec<String>>()).collect::<Vec<Vec<String>>>();
/*for item in (main_vec).iter(){
println!("{:?}",item);
let str24:String=item;
let res=serde_json::from_str(str24);
if res.is_ok(){
let p:Person=res.unwrap();
println!("{}",p.first_name);
println!("{}",p.age);
}
else{
println!("cannot pass the value");
}*/
/*let strings = s.split("},");
println!("{}",strings);
for x in strings {
//println!("{}", x);
let res=serde_json::from_str(x);
if res.is_ok(){
let p:Person=res.unwrap();
println!("{}",p.first_name);
println!("{}",p.age);
println!("-----------------------");
}
else{
println!("cannot pass the value");
}*/
}*/
外部板条箱serde_json;
外部板条箱;
外部板条箱serde_;
使用std::fs::File;
使用std::io::Read;
使用std::str;
使用serde_派生::序列化;
使用serde_派生::反序列化;
#[派生(序列化、反序列化)]
结构人{
名字:String,
姓氏:String,
年龄:164岁,
}
默示人{
fn show(&self){
println!(“名字:{}姓氏:{}年龄:{}”,self.First-Name,self.Last-Name,self.Age);
}
}
fn main(){
让mut file=file::open(“text.json”).unwrap();
让mut data=Vec::new();
file.read_to_end(&mut data).unwrap();
让s=match str::from_utf8(&data){
Ok(v)=>v,
Err(e)=>panic!(“无效的UTF-8序列:{}”,e),
};
let值:Vec=s.split(“},”).collect();
设muti=0;
当我,
呃(e)=>恐慌!(“无效的UTF-8序列:{}”,e),
};*/
//普林顿!(“结果:{}”,s);
/*设str1=String::from(s)*/
//普林顿!(“结果:{}”,str1);
//让main_vec=str1.lines().map(|s | s.trim().split('}').map(String::from).collect::()).collect:();
/*对于(主向量).iter()中的项目{
println!(“{:?}”,项目);
设str24:String=item;
让res=serde_json::from_str(str24);
如果恢复正常(){
让p:Person=res.unwrap();
println!(“{}”,p.first_name);
println!(“{}”,p.age);
}
否则{
println!(“无法传递值”);
}*/
/*设strings=s.split(“},”);
普林顿!(“{}”,字符串);
对于字符串中的x{
//println!(“{}”,x);
设res=serde_json::from_str(x);
如果恢复正常(){
让p:Person=res.unwrap();
println!(“{}”,p.first_name);
println!(“{}”,p.age);
println!(“--------------------------”);
}
否则{
println!(“无法传递值”);
}*/
}*/
这不是答案本身,而是一些想法:通常情况下,您不会直接搜索JSON文件,而是将其读入一个内部数据结构,该结构旨在使您的算法(搜索、更新、删除,可能排序?)简单快速。如果您的文件很长(可能有很多GB),那么一次将文件全部读入内存可能是一个问题,在这种情况下,您可能需要研究使用流式解析器。我认为serde_json支持流式传输,至少它的存在表明了这一点。@trentcl是的,我的意思是任意长,而且如果一次将其加载到内存中是一个问题,那么将其存储在数据库中(每次检查json时都会重建自身)并从中获取信息是一个更好的选择吗?如果是这样的话,那么我可能只需要知道如何在Rust中创建数据库。如果数据库不是一个好的选择(Rust似乎还没有出现,但我没有对它进行广泛的研究),那么我还能做什么呢?通过对文件进行迭代来获得包含所有信息的结构元组是否可行?如果没有,我还有什么其他选择呢?Rust,实际上是cargo,有一个本地数据库。当您安装了一个新的cargo并且第一次进行了cargo build
时,它会更新索引
,持续几秒钟。对于整个安装,而不是每个项目,此操作仅执行一次。我不是铁锈专家,但用“更简单的语言”获取基础知识可能比将其移植到铁锈上更容易。现有的数据库库是一个不错的选择。我不知道有什么东西存在或者对生锈有好处,这对这个网站来说无论如何都是离题的。至于其他选择——你有很多!您需要设计您的数据结构,以便您最想做的任务是最快的。您的数据比简单的JSON文件具有更多的结构;例如,State
可能是一组固定键中的一个,OS
可能包含一组固定键中的多个键,dependens
包含与数据集其他成员的关系。您可以利用这些结构来提高性能和减少膨胀。您可能需要实现一些图遍历算法(例如,拓扑排序会告诉您安装依赖项的顺序),因此您需要考虑到这一点。您可能需要按名称搜索。由您定义需求。建筑问题是这里的主题,但这是一条很好的路线;我想说的是,你应该考虑一个设计,并解释为什么你认为它有问题,而不是让它为你做一个。请在发布答案之前阅读。