最近看别人的代码,发现服务端的接口直接把数据库的实体传给了前端,这可能会导致一些隐患。
比如某实体定义如下
data class LogEntity(
val id: Long,
val desc: String
)
val logEntity = LogEntity(id = 122337203685400001L, desc = "Some description")
转成 JSON 变成了
{
"id":122337203685400001,
"desc":"Some description"
}
然后前端把这个 JSON parse 成 JavaScript 对象,变成了
Object { id: 122337203685400000, desc: "Some description" }
LogEntity 的 ID 个位的 1 变成了 0,出现问题了。
这实际上是一个 JavaScript 的number
类型处理数字的 feature,JavaScript 能准确表示-2^53
到2^53
之间的整数,具体可以看这个文章。然而有的语言的 Long 类型的范围是大于-2^53
到2^53
这个范围的,比如 Java 的Long
的范围为-2^63
到2^63-1
,而在数据库里定义有符号的BIGINT
,往往会用Long
来在应用内存中表示。(当然实际实践中这么大的数字可能比较少见。)
所以比较合适的做法是在定义一个用于传输数据到前端的 DTO,把Long
转成 JSON 支持的string
类型,如
data class LogDTO(
val id: String,
val orderDesc: String
)
val logDTO = LogDTO(id = logEntity.id.toString(), desc = logEntity.desc)
// {"id":"122337203685400001","desc":"Some description"}
在实践中使用专门定义的 DTO 传输数据确实是一个比较好的做法。除了上述的问题,其他的如 JSON 不支持时间,可以用 ISO8601 字符串或 UNIX 时间戳,JSON 不支持byte[]
,可以编码成 Base64 。
所以请不要直接向前端返回定义的用于 CURD 的数据库实体。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.