-
Notifications
You must be signed in to change notification settings - Fork 238
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The se::to_writer
function now requires std::fmt::Write
instead of std::io::Write
#499
Comments
Yes, the reason is because XML is a text-based format which could use many encodings. You should manually encode the string result to bytes for now. If you want an UTF-8 encoded data in let ser = Serializer::new(String::new());
let string: String = data.serialize(ser).unwrap();
let bytes: Vec<u8> = string.into_bytes(); |
That's a fair point. I have a question though: I create a I feel like the actual solution to my use-case would be the ability to call the |
You want to mix serde serializer with event-based Writer API? Could you describe your case better? Also, I suppose you use master, right? |
Basically, I write a bunch of nodes myself through the event-based API. But then the inner part is serialized through Being able to replace something like that writer.write_event(Event::Start(BytesStart::new("foo")))?;
quick_xml::se::to_writer(ToWriteFmt(writer.inner()), &Bar { baz: 42 })?;
writer.write_event(Event::End(BytesEnd::new("foo")))?; with something like this writer
.create_element("foo")
.write_serialized_content(Bar { baz: 42 })?; would be the ideal implementation for my use-case. And yes, I am using |
Yes, I agree that we should have it, but it just not yet implemented. Did you mind to make a PR? Ideally, we should have a reader, that would be able to deserialize objects using |
Yeah I can work on a PR for this, I'll get back to you once it's ready. |
I just tried to upgrade to 0.27 in zbus and was surprised by this change breaking my code. I know it's a different semver release so breaking changes are to be expected but it would have been nice to find any mention of this change and the rationale in either the release notes, or the relevant commit log (4f376b1). In any case, isn't it change making |
Oops, give the incorrect link to the JSON lib. I meant serde_json of course: https://docs.rs/serde_json/latest/serde_json/fn.to_writer.html |
I would think that's true for JSON as well.
Does
So that seems like a counter-argument to using |
Yes, and I think this is oversight in the serde_json. It writes UTF-8 only, which is a task for Our serde writer doesn't write the XML declaration ( Adapter from |
Thanks for explaining.
Are you sure? Is there an issue on serde_json about this? I'm sorry for being skeptical here but this is @dtolnay (the main person behind a lot of Rust's fundamental API, including serde itself) we're talking about.
Yeah but AFAIK Also what about the internal inconsistency with |
I don't known. While @dtolnay can be great in other projects, serde project is not in him focus nowadays and it is effectively frozen as you can see from numerous problems in serde bugtracker those does not get any attention from maintainers.
Yes, it is, but in our case, it is more convenient for us to work internally with a type that protects us from the accidental use of incorrect encoding when writing XML parts (or worse, the use of different encodings when writing different parts). That type is everything that
Difference from reader side in two points:
|
I think io::Write is the better API for to_writer. Pretty near 100% of users of a to_writer API are going to be using it with types that implement io::Write and do not implement fmt::Write. Things like File, BufWriter, BytesMut, Stdout, etc. Forcing near 100% of callers to use a fmt/io adapter would be a worse API regardless of the adapter being zero cost. |
Yeah but both these traits existed when serde was developed so I'm not sure the current state of serde projects is very relevant here.
If this API could be zero-cost, I wouldn't mind at all and can look into contributing it. However, looking at the implementations in std, I don't see how that would work w/o some external crate or new
That's fair and hope you can agree that it'd be nice not to ditch functionality that could be essential for users.
Not sure if this difference is relevant? In case of writing, there is no need for detection. |
That adapter could represent essential entity of XML world -- an XML document, which is a container for XML declaration, DTD, used namespaces. Serde part writes only XML fragments which is not a documents, so writing they to file / network directly could be error-prone for reader (if reader expects standalone XML). This is the case where the explicit is better, than implicit.
It was the answer to why
The simplest adapter is only 10 lines: struct ToFmtWrite<T>(pub T);
impl<T> std::fmt::Write for ToFmtWrite<T>
where
T: std::io::Write,
{
fn write_str(&mut self, s: &str) -> std::fmt::Result {
self.0.write_all(s.as_bytes()).map_err(|_| std::fmt::Error)
}
}
When you write, you himself command which encoding to use (= which bytes to write when you write text string). When you read, XML could contain used encoding inside XML itself (so you need to read XML in some encoding to determine which encoding is used...) |
Nonetheless it would be a good idea to file an issue with serde |
Right, that's a good point.
Ah right, thanks. I was thinking the other way around. |
BTW, is this a new behavior? I'm asking cause my testcase now fails on reading a sample xml when i upgrade with
|
This is because you need to name attributes in your structs starting with a |
After reading all the comments above, I still haven't figure how to write XML to |
For UTF-8 case you can use: use quick_xml::se::to_writer;
use serde::Serialize;
struct ToFmtWrite<T>(pub T);
impl<T> std::fmt::Write for ToFmtWrite<T>
where
T: std::io::Write,
{
fn write_str(&mut self, s: &str) -> std::fmt::Result {
self.0.write_all(s.as_bytes()).map_err(|_| std::fmt::Error)
}
}
#[derive(Serialize)]
struct Xml {
#[serde(rename = "@attribute")]
attribute: &'static str,
element: &'static str,
}
let data = Xml {
attribute: "attribute",
element: "element",
};
let mut io = ToFmtWrite(std::io::stdout());
to_writer(&mut io, &data).unwrap(); |
Is there a reason for this change? It makes it impossible to use this function with a
Vec<u8>
(which does implementstd::io::Write
), while it is still possible in the current released version.The text was updated successfully, but these errors were encountered: