Ich bin sehr neu in Rust - und dieser Code ist Teil eines künstlichen Lernprojektes. Denken Sie daran;)Wie können Backslash-Zeichen in PathBuf-Variablen beim Schreiben in eine JSON-Datei entfernt werden?
Ich habe eine Sammlung von Tupeln: &[(i32, String, String, PathBuf)]
, die in eine Funktion übergeben werden, die entwickelt wurde, um die Daten in eine JSON-Datei zu schreiben.
Das Problem: wenn ich konvertieren die PathBuf
auf ein &str
- der Pfad zu Datei geschrieben unescaped Backslash Zeichen hat, so dass die JSON ist ungültig.
Hier ist der Code:
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(())
}
Und ein Beispiel für die Ausgabe:
{
"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"
}
}
Der Code, der die PathBuf
s für die MetadataPath
s erzeugt, ist wie folgt:
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());
}
Und die count_nonempty_metadata_fields
Funktion:
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))
}
Wenn ich den ursprünglichen Verzeichnispfad Zeichenfolge zu ändern:
let metadata_files = metadata_read::read_filenames_from_dir("C:/Dev/Temp/ReviewQueue/Metadata");
er den Ausgang nicht ändert, z.B.
{
"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"
}
}
Aber es ist immer noch nicht richtig.
Fragen
- Wenn ich mit diesem Ansatz der Aufbau eines
String
in handgefertigten JSON-Format bleiben, wie bekomme ich den Pfad Inhalt derPathBuf
s in ein Format mit entweder vorwärts - Schrägstriche oder Backslashes mit Umrandung? Fehle ich etwas in der API? - Sollte ich ein
Json
Objekt verwenden, um die Daten zu erstellen (die wahrscheinlich zuverlässiger sein wird)? Wenn ja, wie ist der normale Weg, den Inhalt einesJson
Objekts in eine Datei zu schreiben?
Dank für die Tiefe dieser Antwort, zusätzlich zu dem 'PathBuf' /' to_string_lossy() 'info, gibt es eine Reihe von weiteren Verbesserungen zu arbeiten. Was meinen Sie mit„Zusätzlich Ihr Ausgang ein Objekt mit den gleichen zwei Schlüsseln. Obwohl es nicht ungültig ist, ist es wahrscheinlich nicht das, was Sie wollen. "? Sie beziehen sich auf das doppelte Auftreten von 'ReviewItem'? Arbeite auch nicht viel mit 'JSON', aber wenn ich dich richtig interpretiere, kann ich eine" Eine geordnete Liste von Werten "(Array) anstatt" Eine Sammlung von Name/Wert-Paaren "ausgeben (Terminologie von http: // json .org /)? In diesem Fall brauche ich kein 'ReviewItem' ... danke! –
@GavinHope * doppeltes Auftreten von 'ReviewItem' * - ja, das zweite Auftreten des Schlüssels überschreibt das erste Auftreten. Der Code, den ich gezeigt habe, gibt ein JSON-Array von Objekten aus, was auch bedeutet, dass Sie * wahrscheinlich * das Feld 'index' entfernen können (es ist implizit von der Reihenfolge im Array). – Shepmaster
Ja - mit dem geordneten Array brauche ich nicht mehr 'Index', danke. –