I have a struct:
#[derive(Serialize,Deserialize,Debug)]
struct Post {
#[serde(rename(deserialize = "userId"))]
user_id: i32,
id: i32,
title: String,
body: String,
}
I need to deserialize JSON to Vec<Post>:
extern crate restson;
extern crate serde;
extern crate serde_derive;
use std::fs;
use std::path::Path;
use restson::{RestClient, RestPath, Error};
use serde_derive::{Serialize, Deserialize};
const URI: &str ="https://jsonplaceholder.typicode.com/";
impl RestPath<()> for Vec<Post> {
fn get_path(_: ()) -> Result<String, Error> {
Ok(String::from("posts"))
}
}
fn main() {
let mut client = RestClient::new(URI).unwrap();
let posts: Vec<Post> = client.get(()).unwrap();
println!("{:?}", posts.len());
}
I'm totally new, so please help me.
Related
my "main" file
mod router;
mod student;
use std::sync::Arc;
use crate::router::init_router;
use crate::router::Memory;
use actix_web::{App, HttpServer};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv::dotenv().ok();
let repo = Arc::new(Memory::repository());
let host = std::env::var("SERVER.HOST").unwrap_or("127.0.0.1".to_string());
let port = std::env::var("SERVER.PORT").unwrap_or("8080".to_string());
let url = format!("{}:{}", host, port);
println!("url: {}", &url);
HttpServer::new(move || {
App::new()
.data(repo.clone()) // shared
.configure(init_router)
})
.bind(&url)?
.run()
.await
}
my file: "router.rs"
use std::sync::Arc;
use crate::student::Student;
use actix_web::{get, web, HttpResponse, Responder};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Memory {
pub students: Vec<Student>,
}
impl Memory {
fn new() -> Self {
Memory {
students: Vec::new(),
}
}
pub fn repository() -> Self{
Self {
students: vec![
{Student::new("1".to_string(), "Daniel".to_string(), 19)},
{Student::new("2".to_string(), "Lucia".to_string(), 17)},
{Student::new("3".to_string(), "Juan".to_string(), 14)}
]
}
}
}
#[get("/student/list/all")]
async fn list_all(repo: web::Data<Arc<Memory>>) -> impl Responder {
HttpResponse::Ok().json(&***repo)
}
#[get("/student/list/by-id/{id_student}")]
async fn list_by_id(web::Path(id_student): web::Path<String>, repo: web::Data<Arc<Memory>>) -> impl Responder {
HttpResponse::Ok().json(&***repo.students.into_iter().find(|x| *x.id == id_student))
}
pub fn init_router(config: &mut web::ServiceConfig) {
config.service(list_all);
config.service(list_by_id);
}
and my file: "student.rs"
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Student{
pub id: String,
pub nombre: String,
pub calificacion: u32,
}
impl Student{
pub fn new(id: String, nombre: String, calificacion: u32) -> Self{
Self{id, nombre, calificacion}
}
}
I want to show a student in the following path: 127.0.0.1:3000/student/list/by-id/1
but i have the following error
error[E0614]: type `std::vec::IntoIter<Student>` cannot be dereferenced
--> src\router.rs:43:33
|
43 | HttpResponse::Ok().json((&***repo.lock().unwrap().students.into_iter()).find(|x| *x.id == id_student))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
because I get the error, I don't know what is wrong. Please I need help I am new to this programming language.
The dot operating will smartly dereference the pointer, so the following will compile:
&repo.students.iter().find(|x| *x.id == id_student)
the Arc will be dereferenced when accessing students from repo, which will give a reference to the Vec, and .iter() will give you a non-consuming iterator, which you can then map over (.into_iter() will require the Vec to be copied and consumed)
I have the file "user.rs" that has the struct of a postgres database table. Whenever I try to include it in my main.rs file (A Rocket web project), all of the Diesel "stuff" can't resolve. Here is my user.js file:
use super::schema::users;
pub mod handler;
pub mod repository;
pub mod router;
#[derive(Queryable, AsChangeset, Serialize, Deserialize)]
#[table_name = "users"]
pub struct User {
pub id: String,
pub username: String,
pub password: String,
}
#[derive(Insertable)]
#[table_name = "users"]
pub struct InsertableUser {
username: String,
password: String,
}
pub impl InsertableUser {
pub fn from_user(user: User) -> InsertableUser {
InsertableUser {
username: user.username,
password: user.password,
}
}
}
pub fn all(connection: &PgConnection) -> QueryResult<Vec<User>> {
users::table.load::<User>(&*connection)
}
pub fn get(id: i32, connection: &PgConnection) -> QueryResult<User> {
users::table.find(id).get_result::<User>(connection)
}
pub fn insert(user: User, connection: &PgConnection) -> QueryResult<User> {
diesel::insert_into(users::table)
.values(&InsertableUser::from_user(user))
.get_result(connection)
}
pub fn update(id: i32, user: User, connection: &PgConnection) -> QueryResult<User> {
diesel::update(users::table.find(id))
.set(&user)
.get_result(connection)
}
pub fn delete(id: i32, connection: &PgConnection) -> QueryResult<usize> {
diesel::delete(users::table.find(id)).execute(connection)
}
And here is my main.rs:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;
#[macro_use]
extern crate rocket_contrib;
use rocket_contrib::databases::diesel;
#[database("camera-server-db")]
struct CameraServerDbConn(diesel::PgConnection);
mod user;
#[get("/")]
fn index() -> &'static str {
"Hello World!"
}
fn main() {
rocket::ignite()
.attach(CameraServerDbConn::fairing())
.mount("/", routes![index])
.launch();
}
If I remove mod user; from main.rs, no error show up. When I run cargo check, I get many "cannot find x in this scope". Here's an example:
error: cannot find derive macro `AsChangeset` in this scope
--> src/user.rs:7:21
|
7 | #[derive(Queryable, AsChangeset, Serialize, Deserialize)]
| ^^^^^^^^^^^
I'm trying to follow this guide (which is admittedly quite out of date, but it was one of the only actual guides I could find).
As mentioned in the linked guide in the section "The last step", you need to import diesel correctly otherwise the compiler cannot resolve those traits/derives/functions. That means you need to change your main.rs file as following:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;
#[macro_use]
extern crate rocket_contrib;
#[macro_use]
extern crate diesel;
use rocket_contrib::databases::diesel;
#[database("camera-server-db")]
struct CameraServerDbConn(diesel::PgConnection);
mod user;
#[get("/")]
fn index() -> &'static str {
"Hello World!"
}
fn main() {
rocket::ignite()
.attach(CameraServerDbConn::fairing())
.mount("/", routes![index])
.launch();
}
(note the additional #[macro_use] extern crate diesel; in your extern crate section.)
I have trouble deserializing json to struct.
Here is code that simulates my problem:
use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender };
extern crate serde_json;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize, Debug)]
struct Foo<'a> {
a: u32,
b: u32,
c: &'a str,
}
fn main() {
let (msg_tx, msg_rx): (Sender<Foo>, Receiver<Foo>) = mpsc::channel();
{
let js = r#"{"a":33, "b":44, "c": "ss"}"#; // initially I have a json String, here I simulate a problem
let js_string = String::from(js);
let f = test(js_string.as_str());
msg_tx.send(f);
}
}
fn test(js: &str) -> Foo {
let foo: Foo = serde_json::from_str(js).unwrap();
foo
}
Running that code results to the error 'js' does not live long enough.
I know that changing the type of Foo c field to String will resolve the problem, but I would like to know if there is a another solution.
The reason for this error is the way serde crate works in that situation, - it uses inside returned foo variable a reference to original variable, which is js_string, so it goes out of scope just after calling msg_tx.send(f); but f has a reference to it and lives longer than that scope.
I'm still a rust beginner and want to master lifetime concept. I tried to fix my problem with function wrapper to set right lifetime, but failed.
You have to ensure that js_string lives longer than the channel, to ensure this you can create a scope for "working" with the channel:
use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender };
extern crate serde_json;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize, Debug)]
struct Foo<'a> {
a: u32,
b: u32,
c: &'a str,
}
fn main() {
let js = r#"{"a":33, "b":44, "c": "ss"}"#;
let js_string = String::from(js);
let f = test(js_string.as_str());
{
let (msg_tx, msg_rx): (Sender<Foo>, Receiver<Foo>) = mpsc::channel();
msg_tx.send(f);
} // channel is dropped here and js_string is no longer borrowed
} // js_string is dropped here
fn test(js: &str) -> Foo {
let foo: Foo = serde_json::from_str(js).unwrap();
foo
}
My intention is receiving events through WebSockets and use them on the closures of main.
This works when the messages are pure text (String), but the idea is deserializing that text into some structs.
In this example I've added only Data, Error and Event, but in other cases, it could be different, so I've used generics to do that, but I'm a little lost. The compiler has suggested several things that I've tried, but I don't know how to "force" that the message is casted into a specific type (Data in this example, but EventManager could be used on other parts, so it should be generic).
I've attached this code, that tries to show my idea, although it doesn't compile:
events.rs:
use actix::*;
use actix_web::ws::{Client, Message, ProtocolError};
use futures::Future;
use serde::de;
use serde_json::from_str;
struct MyActor<T> {
manager: EventManager<T>,
}
impl<T: 'static> Actor for MyActor<T> {
type Context = Context<Self>;
}
impl<T: 'static> StreamHandler<Message, ProtocolError> for MyActor<T> {
fn handle(&mut self, msg: Message, _ctx: &mut Context<Self>) {
match msg {
Message::Text(text) => {
debug!("Received {}", text);
for idx in 0..self.manager.events.len() {
let data =
from_str(&text).expect(&format!("Error when deserializing {:?}", text));
(self.manager.events[idx].handler)(data)
}
}
_ => panic!(),
}
}
}
pub struct Event<T> {
handler: Box<Fn(T) + 'static>,
}
pub struct EventManager<T> {
events: Vec<Event<T>>,
}
impl<T: 'static> EventManager<T>
where
T: serde::Deserialize<'static>,
{
pub fn new() -> Self {
Self { events: vec![] }
}
pub fn capture<F>(&mut self, function: F)
where
F: for<'h> Fn(T) + 'static,
{
let event = Event {
handler: Box::new(function),
};
self.events.push(event);
}
pub fn run(self) {
let runner = System::new("example");
debug!("run");
Arbiter::spawn(
Client::new("example")
.connect()
.map(|(reader, _writer)| {
MyActor::create(|ctx| {
MyActor::add_stream(reader, ctx);
MyActor { manager: self }
});
})
.map_err(|err| {}),
);
runner.run();
}
}
main.rs:
#[macro_use]
extern crate log;
extern crate actix;
extern crate actix_web;
extern crate env_logger;
extern crate futures;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
pub mod events;
use actix::*;
use serde::de;
use serde::de::{Deserialize, Deserializer};
use events::EventManager;
#[derive(Debug, Message, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Data {
Error(Error),
Event(Event),
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Error {
message: String,
code: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Event {
name: String,
content: String,
}
fn main() {
env_logger::init();
let mut client = EventManager::<Data>new();
client.capture(|data| debug!("event: {:?}", data));
client.run();
}
All the code could be see in https://github.com/foochi/how-deserialize-within-actix
There are some fixes to get it compile.
The trick to get it compile is to use Higher-Rank Trait Bounds (HTRB) trait bounds instead of declaring 'static lifetimes.
Follow the compiler suggestion and bind the T: serde::Deserialize<'_> trait:
impl<T> StreamHandler<Message, ProtocolError> for MyActor<T>
where
for<'de> T: serde::Deserialize<'de> + 'static,
Then change also the Deserialize<'static> trait bound associated to theEventManager impl with a HTRB trait bound to get it compatible with the requirement of StreamHandler implementation:
impl<T: 'static> EventManager<T>
where
for<'de> T: serde::Deserialize<'de>,
Finally, if you correct the line the create the client with the right sintax:
let mut client: EventManager<Data> = EventManager::new();
the example code should compile.
Note: For capture the use of a Higher Trait Bound for declaring the Fn requirement is redundant, do simply:
pub fn capture<F>(&mut self, function: F)
where
F: Fn(T) + 'static,
I'm trying to use the #[primarykey()] macro in Diesel but am getting an error that it is unknown. From what I have found, adding #![feature(primary_key)] should solve the issue, but it doesn't.
lib.rs
#[macro_use]
extern crate diesel;
extern crate dotenv;
pub mod schema;
pub mod models;
use diesel::prelude::*;
use diesel::pg::PgConnection;
use dotenv::dotenv;
use std::env;
pub fn establish_connection() -> PgConnection {
dotenv().ok();
let database_url = env::var("DATABASE_URL")
.expect("DATABASE_URL must be set");
PgConnection::establish(&database_url)
.expect(&format!("Error connecting to {}", database_url))
}
models.rs
#![feature(primary_key)]
extern crate diesel;
#[derive(Queryable, Debug)]
#[primary_key(user_id)]
pub struct User {
pub user_id: i32,
pub email: String,
pub password: String,
pub bio: String,
pub verified: bool,
}
I've also tried adding #![feature(primary_key)] to the top of lib.rs without any luck.
Using Rust 1.26.0-nightly (80785a547 2018-03-30)
The primary_key attribute is only applicable when deriving Identifiable:
#[macro_use]
extern crate diesel;
mod schema {
table! {
users (user_id) {
user_id -> Int4,
email -> Text,
}
}
#[derive(Debug, Identifiable)]
#[primary_key(email)]
pub struct User {
pub user_id: i32,
pub email: String,
}
}
fn main() {}
I believe you could also just change your primary key in your schema definition (users (user_id)).