You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用R与DuckDB实现列的序列化与反序列化问题排查

序列化HTML列与DuckDB交互的问题及解决方案

已验证解决方案

感谢@r2evans的解答,针对该场景的可行方案如下:

  • 写入数据库时,对目标列执行序列化:
    dplyr::mutate(x = sapply(.data$x, serialize, connection = NULL))
    
  • 从数据库读取后,反序列化并恢复HTML类型:
    dplyr::mutate(x = lapply(.data$x, \(x) htmltools::HTML(unserialize(x))))
    

问题详情

需要将包含HTML类型列的数据框写入DuckDB,因原始数据类型与数据库不兼容,先对该列做序列化处理,但从数据库读取后无法将其反序列化为原始HTML类型。

可复现示例

基础数据构造:

df <- tibble::tibble(x = 1:5, y = letters[1:5])

# A tibble: 5 × 2
      x y    
  <int> <chr>
1     1 a    
2     2 b    
3     3 c    
4     4 d    
5     5 e    

序列化目标列后的数据:

input <- df |> dplyr::mutate(x = lapply(x, serialize, NULL))

# A tibble: 5 × 2
  x          y    
  <list>     <chr>
1 <raw [35]> a    
2 <raw [35]> b    
3 <raw [35]> c    
4 <raw [35]> d    
5 <raw [35]> e  

写入并读取DuckDB:

conn <- duckdb::dbConnect(duckdb::duckdb(), ":memory:")

duckdb::dbWriteTable(conn, "df", input)

output <- DBI::dbGetQuery(conn, "SELECT * FROM df") |> tibble::as_tibble()

# A tibble: 5 × 2    
  x          y    
  <list>     <chr>
1 <raw [35]> a    
2 <raw [35]> b    
3 <raw [35]> c    
4 <raw [35]> d    
5 <raw [35]> e   

针对基础int类型的反序列化能正常恢复,但实际HTML场景异常:

output |> dplyr::mutate(x = lapply(x, unserialize))

# A tibble: 5 × 2
  x         y    
  <list>    <chr>
1 <int [1]> a    
2 <int [1]> b    
3 <int [1]> c    
4 <int [1]> d    
5 <int [1]> e  

补充说明

实际场景中,序列化的列存储的是HTML字符串,序列化前的数据结构:

# A tibble: 5 × 2    
  x      y    
  <list> <chr>
1 <html> a    
2 <html> b    
3 <html> c    
4 <html> d    
5 <html> e  

执行反序列化代码后,得到不符合预期的结果:

# A tibble: 5 × 2    
  x      y    
  <list> <chr>
1 <raw>  a    
2 <raw>  b    
3 <raw>  c    
4 <raw>  d     
5 <raw>  e  

更多信息

序列化前后的数据详情:

> before[1]
[[1]]
<a href='data:text/csv;base64,Zm9v' download='foo.csv'><button style='background-color:#67C2DC; color:white; border:none; padding:5px;font-weight:bold; cursor:pointer; border-radius:4px; font-size:12px;'>CSV</button></a>

> after[1]
[[1]]
   [1] 58 0a 00 00 00 03 00 04 04 01 00 03 05 00 00 00 00 05 55 54 46 2d 38 00 00 00 18 00 02 8c 7a 58 0a 00 00 00 03
...
 [ reached getOption("max.print") -- omitted 166065 entries ]

> class(before)
[1] "list"
> class(before[1])
[1] "list"
> class(before[1][[1]])
[1] "html"      "character"

> class(after)
[1] "list"
> class(after[1])
[1] "list"
> class(after[1][[1]])
[1] "raw"

尝试所有现有建议均无效,反序列化后始终得到<raw>类型数据:

> unserialize(after[1][[1]])
   [1] 58 0a 00 00 00 03 00 04 04 01 00 03 05 00 00 00 00 05 55 54 46 2d 38 00 00 00 18 00 02 8c 5b 58 0a 00 00 00 03
  ...

内容的提问来源于stack exchange,提问作者FISR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 00:03:14