json icon indicating copy to clipboard operation
json copied to clipboard

Expose a way to read an io::Read into string and deserialize from the string

Open dtolnay opened this issue 7 years ago • 8 comments

https://github.com/SergioBenitez/Rocket/pull/547 wants to do the following two steps but get a single serde_json::Error out, rather than an io::Error and a serde_json::Error.

let mut s = String::new();
data.read_to_string(&mut s)?;
let t = serde_json::from_str(&s)?;

dtolnay avatar Jan 24 '18 18:01 dtolnay

One possible way to expose this would be relaxing the bound on serde_json::from_reader to accept some sealed trait that is implemented for all io::Read as well as for an adapter that indicates eager reading to string (naming tbd).

fn from_reader<R, T>(reader: R) -> Result<T>
where
    R: Read2,
    T: DeserializeOwned;

trait Read2: Sealed { /* ... */ }
impl<R> Read2 for R where R: io::Read { /* ... */ }
impl<R> Read2 for Adapter<R> where R: io::Read { /* ... */ }

struct Adapter<R>(R);

dtolnay avatar Jan 24 '18 18:01 dtolnay

@dtolnay Extending from_reader like that would be great. Alternatively, you could add a secondary function so that the interface doesn't get so complicated. Two options are:

/// Reads all of `reader` into a `String` then deserialized into `T`.
fn from_reader_eager<R: io::Read, T: DeserializeOwned>(reader: R) -> Result<T>;

/// Reads at most `max` number of bytes into a `String` then deserialized into `T`.
fn from_reader_bounded<R: io::Read, T: DeserializeOwned>(reader: R, max: usize) -> Result<T>;

SergioBenitez avatar Jan 25 '18 00:01 SergioBenitez

@dtolnay What do you think?

SergioBenitez avatar Jan 29 '18 21:01 SergioBenitez

My feeling is that the use case of not being able to handle an io::Error is not common enough to deserve a top-level serde_json::from_reader_eager function. I would prefer to come up with some other alternatives that are "better hidden".

dtolnay avatar Jan 29 '18 22:01 dtolnay

Can we just use #[doc(hidden)] on the function?

SergioBenitez avatar Feb 12 '18 22:02 SergioBenitez

@messense @SergioBenitez to unblock things for Rocket I published from_reader_eager in a separate crate. Once we figure out the right API on the serde_json side we can update that implementation to use it. I invited Sergio as an owner.

dtolnay avatar Feb 15 '18 18:02 dtolnay

@dtolnay Can we just copy that function into Rocket verbatim? Perhaps with a note in serde, similar to the json! macro, that Rocket is using this private method?

SergioBenitez avatar Feb 16 '18 03:02 SergioBenitez

Yes that should be fine.

dtolnay avatar Feb 16 '18 03:02 dtolnay