Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在写入JSON文件时转义PathBuf变量中的反斜杠字符?_Json_Rust - Fatal编程技术网

如何在写入JSON文件时转义PathBuf变量中的反斜杠字符?

如何在写入JSON文件时转义PathBuf变量中的反斜杠字符?,json,rust,Json,Rust,我对Rust很陌生,这段代码是一个人工学习项目的一部分。记住这一点;) 我有一组元组:&[(i32,String,String,PathBuf)],它们被传递到一个函数中,该函数用于将数据写入JSON文件 问题:当我将PathBuf转换为&str时-写入文件的路径具有未转换的反斜杠字符,因此JSON无效 代码如下: use std::io; use std::io::prelude::*; use std::fs::File; use std::path::PathBuf; pub fn wr

我对Rust很陌生,这段代码是一个人工学习项目的一部分。记住这一点;)

我有一组元组:
&[(i32,String,String,PathBuf)]
,它们被传递到一个函数中,该函数用于将数据写入JSON文件

问题:当我将
PathBuf
转换为
&str
时-写入文件的路径具有未转换的反斜杠字符,因此JSON无效

代码如下:

use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::path::PathBuf;

pub fn write_review_queue(ordered_review_queue: &[(i32, String, String, PathBuf)]) -> io::Result<()> {
    let output_file = "C:\\Dev\\Temp\\ReviewQueue\\review_queue.json";
    let mut buffer = try!(File::create(output_file));
    try!(buffer.write("{".to_string().as_bytes()));

    let mut is_first_item = true;
    for review_item in ordered_review_queue {
        if !is_first_item {
            try!(buffer.write(",".to_string().as_bytes()));
        }
        is_first_item = false;

        let json_string = "\"ReviewItem\": ".to_string() +
                          "{\"Index\": " + &review_item.0.to_string() + 
                          ", \"ReviewItemName\": \"" + &review_item.1 +
                          "\", \"ReviewItemPath\": \"" + &review_item.2 +
                          "\", \"MetadataPath\": \"" +  review_item.3.to_str().unwrap() +
                          "\"}";

        try!(buffer.write(json_string.as_bytes()));
    }


    try!(buffer.write("}".to_string().as_bytes()));
    Ok(())
}
MetadataPath
s生成
PathBuf
s的代码如下:

let metadata_files = metadata_read::read_filenames_from_dir("C:\\Dev\\Temp\\ReviewQueue\\Metadata");
    if !metadata_files.is_ok() {
        println!("reading metadata filenames failed");
        return;
    }

    let mut metadata_counts = Vec::new();
    for file in metadata_files.unwrap() {
        let metadata_field_count = metadata_read::count_nonempty_metadata_fields(&file, &keys);
        metadata_counts.push(metadata_field_count.unwrap());
    }
以及
count\u nonempty\u metadata\u字段
功能:

pub fn count_nonempty_metadata_fields(file_path: &PathBuf, metadata_keys: &[String]) -> Result<(i32, String, String, PathBuf), io::Error>
{
    // a bunch of code here...

    let path = file_path.to_path_buf();
    Ok((key_count, review_item_name, review_item_path, path))
}
它确实会改变输出,例如

{
    "ReviewItem": {
        "Index": 1,
        "ReviewItemName": "Crying Cat",
        "ReviewItemPath": "C:/Temp",
        "MetadataPath": "C:/Dev/Temp/ReviewQueue/Metadata\cryingcat.json"
    },
    "ReviewItem": {
        "Index": 2,
        "ReviewItemName": "Rusty Rat",
        "ReviewItemPath": "C:/Temp",
        "MetadataPath": "C:/Dev/Temp/ReviewQueue/Metadata\rustyrat.json"
    }
}
但这仍然不对

问题

  • 如果我坚持使用手工制作的JSON格式构建
    字符串
    ,那么如何将
    PathBuf
    s的路径内容转换为带有正斜杠或转义反斜杠的格式?我在API中遗漏了什么吗
  • 我是否应该使用
    Json
    对象来构建数据(这可能更可靠)?如果是这样,将
    Json
    对象的内容写入文件的正常方式是什么
  • 最好不要手动生成任何结构化格式,因为最终输出将出现格式错误。此外,您的输出有一个具有相同两个键的对象。虽然不是无效的,但它可能不是你想要的

    在这种情况下,您将很快遇到墙,试图避开引号和反斜杠,可能还有撇号和符号。您还必须手动跟踪最后一项。让图书馆来做这项艰苦的工作吧

    Rust有两个很好的JSON库:和

    第一步是为数据创建一些实际类型。元组很好,但是你真的会记得
    foo.1
    就是这个名字吗。。。还是说它是foo.2

    一旦完成,您可以简单地输出切片:

    extern crate rustc_serialize;
    
    use rustc_serialize::json;
    
    use std::io;
    use std::io::prelude::*;
    use std::fs::File;
    use std::path::PathBuf;
    
    #[derive(RustcEncodable)]
    struct Item {
        index: i32,
        name: String,
        path: String,
        metadata_path: PathBuf,
    }
    
    fn write_review_queue(ordered_review_queue: &[Item]) -> io::Result<()> {
        let mut buffer = try!(File::create("/tmp/output"));
    
        write!(buffer, "{}", json::as_json(&ordered_review_queue))
    }
    
    fn main() {
        let a = [Item { index: 0, name: "He\"llo".into(), path: "Good\\bye".into(), metadata_path: PathBuf::from(r#"C:\path\with'n\special"\chars"#)}];
        write_review_queue(&a).expect("Failed");
    }
    
    重要的是要知道
    PathBuf
    s是而不是字符串。具体来说,它们是依赖于平台的抽象。在类Unix系统上,路径是接近UTF-8但不是UTF-8的字节集合,在Windows上,路径接近但不是UCS-2

    您必须决定什么样的有损转换适合将其转换为真正的UTF-8。我将使用标准库中内置的。我还为类型实现了
    ToJson
    ,以允许更多定制:

    extern crate rustc_serialize;
    
    use rustc_serialize::json::{self, ToJson, Json};
    
    use std::io;
    use std::io::prelude::*;
    use std::fs::File;
    use std::path::PathBuf;
    use std::collections::BTreeMap;
    
    struct Item {
        index: i32,
        name: String,
        path: String,
        metadata_path: PathBuf,
    }
    
    impl ToJson for Item {
        fn to_json(&self) -> Json {
            let mut obj = BTreeMap::new();
            obj.insert("Index".to_string(), self.index.to_json());
            obj.insert("ReviewItemName".to_string(), self.name.to_json());
            obj.insert("ReviewItemPath".to_string(), self.path.to_json());
            obj.insert("MetadataPath".to_string(), self.metadata_path.to_string_lossy().to_json());
            obj.to_json()
        }
    }
    
    fn write_review_queue(ordered_review_queue: &[Item]) -> io::Result<()> {
        let mut buffer = try!(File::create("/tmp/output"));
    
        write!(buffer, "{}", json::as_json(&ordered_review_queue.to_json()))
    }
    
    fn main() {
        let a = [Item { index: 0, name: "He\"llo".into(), path: "Good\\bye".into(), metadata_path: PathBuf::from(r#"C:\path\with'n\special"\chars"#)}];
        write_review_queue(&a).expect("Failed");
    }
    

    感谢这个答案的深度,除了
    PathBuf
    /
    to_string\u lossy()
    信息之外,还有许多其他改进需要解决。您所说的“另外,您的输出有一个具有相同两个键的对象。虽然不是无效的,但它可能不是您想要的。”?您指的是重复出现的
    ReviewItem
    ?也不太适用于
    JSON
    ,但是,如果我正确解释了您的意思,我可以输出一个“有序的值列表”(数组),而不是“名称/值对集合”(术语来源)?在这种情况下,我不需要
    ReviewItem
    。。。谢谢@GavinHope双重出现
    ReviewItem
    -是,第二次出现的键将覆盖第一次出现的键。我展示的代码确实输出了一个JSON对象数组,这也意味着您可能可以删除
    索引
    字段(它是从数组中的顺序中隐式的)。是的-对于有序数组,我不再需要
    索引
    ,谢谢。
    extern crate rustc_serialize;
    
    use rustc_serialize::json;
    
    use std::io;
    use std::io::prelude::*;
    use std::fs::File;
    use std::path::PathBuf;
    
    #[derive(RustcEncodable)]
    struct Item {
        index: i32,
        name: String,
        path: String,
        metadata_path: PathBuf,
    }
    
    fn write_review_queue(ordered_review_queue: &[Item]) -> io::Result<()> {
        let mut buffer = try!(File::create("/tmp/output"));
    
        write!(buffer, "{}", json::as_json(&ordered_review_queue))
    }
    
    fn main() {
        let a = [Item { index: 0, name: "He\"llo".into(), path: "Good\\bye".into(), metadata_path: PathBuf::from(r#"C:\path\with'n\special"\chars"#)}];
        write_review_queue(&a).expect("Failed");
    }
    
    [{"index":0,"name":"He\"llo","path":"Good\\bye","metadata_path":[67,58,92,112,97,116,104,92,119,105,116,104,39,110,92,115,112,101,99,105,97,108,34,92,99,104,97,114,115]}]
    
    extern crate rustc_serialize;
    
    use rustc_serialize::json::{self, ToJson, Json};
    
    use std::io;
    use std::io::prelude::*;
    use std::fs::File;
    use std::path::PathBuf;
    use std::collections::BTreeMap;
    
    struct Item {
        index: i32,
        name: String,
        path: String,
        metadata_path: PathBuf,
    }
    
    impl ToJson for Item {
        fn to_json(&self) -> Json {
            let mut obj = BTreeMap::new();
            obj.insert("Index".to_string(), self.index.to_json());
            obj.insert("ReviewItemName".to_string(), self.name.to_json());
            obj.insert("ReviewItemPath".to_string(), self.path.to_json());
            obj.insert("MetadataPath".to_string(), self.metadata_path.to_string_lossy().to_json());
            obj.to_json()
        }
    }
    
    fn write_review_queue(ordered_review_queue: &[Item]) -> io::Result<()> {
        let mut buffer = try!(File::create("/tmp/output"));
    
        write!(buffer, "{}", json::as_json(&ordered_review_queue.to_json()))
    }
    
    fn main() {
        let a = [Item { index: 0, name: "He\"llo".into(), path: "Good\\bye".into(), metadata_path: PathBuf::from(r#"C:\path\with'n\special"\chars"#)}];
        write_review_queue(&a).expect("Failed");
    }
    
    [{"Index":0,"MetadataPath":"C:\\path\\with'n\\special\"\\chars","ReviewItemName":"He\"llo","ReviewItemPath":"Good\\bye"}]