2 votes

Désérialisation de JSON dans un autre format - Serde_JSON

J'essaie de lire le JSON d'un fichier en Rust qui a les dimensions suivantes :

{
    "DIPLOBLASTIC":"Characterizing the ovum when it has two primary germinallayers.",
    "DEFIGURE":"To delineate. [Obs.]These two stones as they are here defigured. Weever.",
    "LOMBARD":"Of or pertaining to Lombardy, or the inhabitants of Lombardy.",
    "BAHAISM":"The religious tenets or practices of the Bahais."
}

Je veux stocker chaque mot et sa description dans un vecteur (c'est pour un jeu de pendu). Je peux lire le fichier s'il est formaté comme ceci :

[
    {
        "word": "DIPLOBLASTIC",
        "description": "Characterizing the ovum when it has two primary germinallayers."
    },
    {
        "word": "DEFIGURE",
        "description": "To delineate. [Obs.]These two stones as they are here defigured. Weever."
    }
]

Je fais cela en utilisant le code suivant :

#[macro_use]
extern crate serde_derive;

use serde_json::Result;
use std::fs;

#[derive(Deserialize, Debug)]
struct Word {
    word: String,
    description: String,
}

fn main() -> Result<()> {
    let data = fs::read_to_string("src/words.json").expect("Something went wrong...");
    let words: Vec<Word> = serde_json::from_str(&data)?;
    println!("{}", words[0].word);
    Ok(())
}

Cependant, j'essaie de trouver comment conserver le formatage original du fichier JSON sans le convertir en mot et description dans le deuxième exemple JSON.

Est-il possible d'utiliser le format JSON existant ou dois-je le reformater ?

3voto

BallpointBen Points 3265

Vous pouvez rassembler la carte dans un HashMap o BTreeMap puis utiliser ses paires clé-valeur pour créer un vecteur de mots.

fn main() -> Result<()> {
    let data = r#"{
        "DIPLOBLASTIC":"Characterizing the ovum when it has two primary germinallayers.",
        "DEFIGURE":"To delineate. [Obs.]These two stones as they are here defigured. Weever.",
        "LOMBARD":"Of or pertaining to Lombardy, or the inhabitants of Lombardy.",
        "BAHAISM":"The religious tenets or practices of the Bahais."
    }"#;
    let words: std::collections::BTreeMap<String, String> = serde_json::from_str(data)?;
    let words = words
        .into_iter()
        .map(|(word, description)| Word { word, description })
        .collect::<Vec<_>>();
    println!("{:#?}", words);
    Ok(())
}

3voto

PitaJ Points 4168

Si vous voulez économiser les allocations et les itérations, vous pouvez le faire avec une implémentation personnalisée de deserialize :

#[macro_use]
extern crate serde_derive;

use std::fmt;
use serde::de::{Deserialize, Visitor, MapAccess};

#[derive(Deserialize, Debug)]
struct Word {
    word: String,
    description: String,
}

#[derive(Debug)]
struct WordList {
    list: Vec<Word>,
}

#[derive(Debug)]
struct WordListVisitor;

impl<'de> Visitor<'de> for WordListVisitor {
    type Value = WordList;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a string->string map")
    }

    fn visit_map<A: MapAccess<'de>>(self, mut access: A) -> Result<Self::Value, A::Error> {
        let mut list = Vec::with_capacity(access.size_hint().unwrap_or(0));

        while let Some((word, description)) = access.next_entry()? {
            list.push(Word { word, description });
        }

        Ok(WordList { list })
    }
}

impl<'de> Deserialize<'de> for WordList {
    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_map(WordListVisitor)
    }
}

fn main() -> serde_json::Result<()> {
    let data = r#"{
        "DIPLOBLASTIC":"Characterizing the ovum when it has two primary germinallayers.",
        "DEFIGURE":"To delineate. [Obs.]These two stones as they are here defigured. Weever.",
        "LOMBARD":"Of or pertaining to Lombardy, or the inhabitants of Lombardy.",
        "BAHAISM":"The religious tenets or practices of the Bahais."
    }"#;
    let words: WordList = serde_json::from_str(data)?;
    println!("{:#?}", words);
    Ok(())
}

terrain de jeu

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X