首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >tokio_postgres:将Json序列化为Vec<i32>

tokio_postgres:将Json序列化为Vec<i32>
EN

Stack Overflow用户
提问于 2022-05-24 22:53:13
回答 1查看 374关注 0票数 1

TLDR:给定一个包含Json数组的列返回行的查询:

代码语言:javascript
复制
 id |  name   | post_ids 
----+---------+----------
 1  | JohnDoe | [1,2]

使用tokio_postgres将其序列化到User模型-which中包含一个post_ids: Vec<i32>字段--似乎是不可能的。

代码语言:javascript
复制
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct User {
  pub id: String,
  pub name: String,
  pub post_ids: Vec<i32>
}

尝试为tokio_postgres::types::FromSql实现i32,但它只允许用于结构。

我想知道在这个Json和Vec<i32>之间转换的常见方式是什么。

包含完整代码的长版本:

我有一个带有UserPost模型的Postgres数据库:

代码语言:javascript
复制
 id |  name   
----+---------
  1 | JohnDoe
代码语言:javascript
复制
 id |    title    | user_id 
----+-------------+---------
  1 | first post  |       1
  2 | second post |       1

我有一个函数来检索用户以及数据库中的帖子。我知道我可以做得更好,但我的问题是这个函数返回的是posts_ids

代码语言:javascript
复制
create function user_get_one(
  user_id int
)
returns table (
  "id"      text,
  "name"    text,
  post_ids  json
) AS $$
  select
    "user"."id",
    "user"."name",
    (select to_json(array_agg("posts"."id"))
      from (
        select
          "id"
        from
          "post"
        where
          "post"."user_id" = user_id
      ) posts
    ) posts_ids
  from "user"
  where
    "user".id = user_id;
$$ language sql;

这里是一个包含所有DB的小提琴

现在,为了测试目的,我想要一个Rust中的API,它连接到这个DB,调用这个函数,实例化适当的模型,并在控制台中打印数据,不返回任何内容:

Cargo.toml:

代码语言:javascript
复制
[package]
name = "test"
version = "0.1.0"
edition = "2018"

[dependencies]
tokio-postgres = "0.7.5"
tokio = { version = "1.14.0", features = ["full"] }

进口:

代码语言:javascript
复制
use tokio_postgres::{NoTls, Row};

模型:

代码语言:javascript
复制
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct User {
  pub id: String,
  pub name: String,
  // pub post_ids: Vec<i32>, // Uncomment
}

impl From<Row> for User {
  fn from(row: Row) -> Self {
    Self {
      id: row.get("id"),
      name: row.get("name"),
      // post_ids: row.get("post_ids"), // Uncomment
    }
  }
}

其主要职能如下:

代码语言:javascript
复制
#[tokio::main]
async fn main() -> () {
  let (client, connection) = tokio_postgres::connect(
    "postgresql://localhost/rc_forum?user=test_user&password=secret_password ",
    NoTls,
  )
  .await
  .unwrap();

  tokio::spawn(async move {
    if let Err(e) = connection.await {
      eprintln!("connection error: {}", e);
    }
  });

  // Now we can execute a simple statement that just returns its parameter.
  let result = client
    .query_one("select * from user_get_one($1)", &[&1])
    .await
    .unwrap();

  let user: User = User::from(result);

  println!("-----------");
  println!("{:#?}", user);
  println!("-----------");
}

以下是锈菌操场的完整代码:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=677a4f7710f6a29c7e33d3228679881f

现在,有了posts_ids注释,用户就被加载并实例化了;但是,如果我们取消注释posts_idspostgres_tokio就不能转换类型:

代码语言:javascript
复制
error retrieving column post_ids: error deserializing column 2: 
cannot convert between the Rust type `alloc::vec::Vec<i32>` and the Postgres type `json`',

在这个Json和Vec<i32>之间转换的通用方式是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-24 23:52:03

我对Rust或tokio_postgres不太了解,但我想认为锈蚀矢量基本上是一个可以增长的数组--相当于Postgres数组。Vec<i32>是四字节整数的锈蚀向量.我认为这不能接受Postgres的json值。使用整数的Postgres数组(int[])代替:

在此过程中,我将您的复杂功能简化了一点:

代码语言:javascript
复制
CREATE FUNCTION user_get_one(_user_id int)
  RETURNS TABLE (id text, name text, post_ids int[])
  LANGUAGE sql AS
$func$
SELECT u.id
     , u.name
     , ARRAY(SELECT p.id FROM post p
             WHERE p.user_id = _user_id) AS posts_ids
FROM   "user" u  -- very unfortunate name!
WHERE  u.id = _user_id;
$func$;

db<>fiddle https://dbfiddle.uk/?rdbms=postgres_14&fiddle=61a61b5f102259498939b2ed26e25908

关于数组构造函数:

我将向子查询中添加一个ORDER BY子句,以获得一个确定的结果。否则,下一个调用可能使用不同的排序顺序报告相同的数组。所以:

代码语言:javascript
复制
...
 , ARRAY(SELECT p.id FROM post p
         WHERE p.user_id = _user_id ORDER BY 1) AS posts_ids
...

如果您已经有了一个JSON数组,下面是如何转换它:

旁白:不要像“用户”一样使用保留字作为Postgres标识符。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72370262

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档