jeroen / jsonlite

A Robust, High Performance JSON Parser and Generator for R
http://arxiv.org/abs/1403.2805
Other
377 stars 40 forks source link

toJSON encodes single backslashes as literal "\\" #353

Closed dagtann closed 3 years ago

dagtann commented 3 years ago

Summary

When pushing character vectors that contain literal backslashes, e.g., "foo\bar" through jsonlite::toJSON, the resulting array will be "foo\\bar".

Could some internal jsonlite function lead to doubly escaped backslashes?

Repex

writeLines(jsonlite::toJSON("foo\\bar"), con = "my_file.txt")

The output file my_file.txt contains a single line: ["foo\\bar"].

Session information

R version 4.0.3 (2020-10-10)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.1 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8    LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] tidyselect_1.1.0      rapido_0.0.0.9010     remotes_2.2.0         purrr_0.3.4           colorspace_1.4-1     
 [6] vctrs_0.3.4           generics_0.0.2        testthat_2.3.2        usethis_1.6.3         htmltools_0.5.0      
[11] viridisLite_0.3.0     plotly_4.9.2.1        rlang_0.4.8           pkgbuild_1.1.0        later_1.1.0.1        
[16] pillar_1.4.6          glue_1.4.2            withr_2.3.0           sessioninfo_1.1.1     lifecycle_0.2.0      
[21] stringr_1.4.0         munsell_0.5.0         gtable_0.3.0          htmlwidgets_1.5.2     devtools_2.3.2       
[26] memoise_1.1.0         callr_3.5.1           fastmap_1.0.1         httpuv_1.5.4          ps_1.4.0             
[31] esOutput_0.0.0.9000   fansi_0.4.1           Rcpp_1.0.5            xtable_1.8-4          openssl_1.4.3        
[36] promises_1.1.1        scales_1.1.1          backports_1.1.10      desc_1.2.0            pkgload_1.1.0        
[41] jsonlite_1.7.1        fs_1.5.0              mime_0.9              askpass_1.1           ggplot2_3.3.2        
[46] digest_0.6.26         stringi_1.5.3         processx_3.4.4        dplyr_1.0.2           shiny_1.5.0          
[51] shinycssloaders_1.0.0 grid_4.0.3            rprojroot_1.3-2       cli_2.1.0             tools_4.0.3          
[56] magrittr_1.5          lazyeval_0.2.2        tibble_3.0.4          crayon_1.3.4          tidyr_1.1.2          
[61] pkgconfig_2.0.3       ellipsis_0.3.1        redux_1.1.0           data.table_1.13.2     shinyBS_0.61         
[66] prettyunits_1.1.1     shinydashboard_0.7.1  assertthat_0.2.1      httr_1.4.2            rstudioapi_0.11      
[71] R6_2.4.1              compiler_4.0.3 
jeroen commented 3 years ago

It is not double escaped, a backslash needs to be escaped in json and that is what happens. You may be confused by how R prints strings?

x = "foo\\bar"
cat(x, "\n")
cat(jsonlite::toJSON(x), "\n")
identical(x, jsonlite::fromJSON(jsonlite::toJSON(x)))

The output file my_file.txt contains a single line: ["foo\\bar"].

Yes that is the only correct json. If it would be ["foo\bar"] then the \b would be parsed as a backspace character.

dagtann commented 3 years ago

I am not confused by R's internal representation. However, your hint that "foo\\bar" is the only correct JSON lead me to the source of the problem: https://www.tutorialspoint.com/json_simple/json_simple_escape_characters.htm. Thank you!