tafia / quick-xml

Rust high performance xml reader and writer
MIT License
1.21k stars 236 forks source link

How to pretty-print with serde? #361

Closed troelsarvin closed 2 years ago

troelsarvin commented 2 years ago

Hello,

I have the code below; when it runs, it results in the following output:

seralized:
<osm><node visible="true" timestamp="2022-02-17T13:55:16.184553291Z"><tag k="key1" v="value1"/><tag k="key2" v="value2"/></node></osm>

I would like to print it in a prettyfied way, i.e. with indention and line breaks following the XML structure. How can that be done?

use serde::Serialize;
use quick_xml::se;
use chrono::{ DateTime, Utc };

#[derive(Serialize, Clone, Debug)]
#[serde(rename = "tag")]
#[serde(rename_all = "lowercase")]
struct OsmTag {
    k: String,
    v: String,
}

#[derive(Serialize, Clone, Debug)]
#[serde(rename = "node")]
#[serde(rename_all = "lowercase")]
struct OsmNode {
    #[serde(skip_serializing_if = "Option::is_none")]
    id: Option<u64>,
    visible: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    version: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    changeset: Option<u64>,
    timestamp: DateTime<Utc>,
    #[serde(skip_serializing_if = "Option::is_none")]
    user: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    uid: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    lat: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    lon: Option<f64>,
    tag: Vec<OsmTag>,
}

impl Default for OsmNode {
    fn default() -> OsmNode {
        OsmNode {
            id: None,
            visible: true,
            version: None,
            changeset: None,
            timestamp: Utc::now(),
            user: None,
            uid: None,
            lat: None,
            lon: None,
            tag: Vec::new()
        }
    }
}

#[derive(Serialize, Debug)]
#[serde(rename = "osm")]
#[serde(rename_all = "lowercase")]
struct OsmNodeContainer {
    node: OsmNode,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut on = OsmNode { ..Default::default() };
    let t1 = OsmTag { k: String::from("key1"), v: String::from("value1") };
    let t2 = OsmTag { k: String::from("key2"), v: String::from("value2") };
    on.tag.push(t1.clone());
    on.tag.push(t2.clone());
    let onc = OsmNodeContainer { node: on.clone(), };
    let ser = se::to_string(&onc)?;
    println!("seralized:");
    println!("{}", ser);

    Ok(())
}
Mingun commented 2 years ago

Pretty-printing not supported yet, PR is welcome. Be noted, however, that I plan a big rework of a serializer in the coming months

Mingun commented 2 years ago

When #490 will be merged, pretty-print will work

gdesmott commented 1 year ago

When #490 will be merged, pretty-print will work

Can you please explain how it's meant to work? I didn't find any API for pretty-print serialization.

thanks!

Mingun commented 1 year ago

Create Serializer and setup indent

noguxun commented 1 year ago

For anyone who needs a quick example of adding indentation when do serializing

    use serde::Serialize;
    use quick_xml::se::Serializer;

    #[derive(Debug, PartialEq, Serialize)]
    struct Struct {
        question: String,
        answer: u32,
    }

    let data = Struct {
        question: "The Ultimate Question of Life, the Universe, and Everything".into(),
        answer: 42,
    };

    let mut buffer = String::new();
    let mut ser = Serializer::new(&mut buffer);
    ser.indent(' ', 2);

    data.serialize(ser).unwrap();

    println!("{buffer}");
Mingun commented 1 year ago

@noguxun, feel free to make a PR that improves documentation (example for indent and maybe a mention in Serializer doc)

Type1J commented 1 month ago

I was expecting a to_string_pretty(options: ToStringPrettyOptions). I believe that API is similar to other serde format libraries.