json - 将 json null 解组为 NullString 的指针
问题描述
我无法将json.Unmarshal
空值放入*NullString
结构内的字段中。这是我的意思的简化示例:
package main
import (
"database/sql"
"encoding/json"
"log"
)
// NullString
type NullString struct {
sql.NullString
}
func (n *NullString) UnmarshalJSON(b []byte) error {
n.Valid = string(b) != "null"
e := json.Unmarshal(b, &n.String)
return e
}
type Person struct {
Name *NullString `json:"name"`
}
func BuildUpdateSQL(jsonString string) string {
p := Person{}
e := json.Unmarshal([]byte(jsonString),&p)
if e != nil {
log.Println(e)
}
if p.Name != nil {
log.Println(p,p.Name)
} else {
log.Println(p)
}
return ""
}
func main() {
// Correctly leaves p.Name unset
BuildUpdateSQL(`{"field_not_exist":"samantha"}`)
// Correctly sets p.Name
BuildUpdateSQL(`{"name":"samantha"}`)
// Incorrectly leaves p.Name as nil when I really want p.Name to have a NullString with .Valid == false
BuildUpdateSQL(`{"name":null}`)
}
如您所见,解编组适用于非空 json 值。但是当我传入一个 null json 值时, NullString 解组器似乎甚至没有触发。
有人知道我在做什么错吗?
背景
我尝试这样做的原因是因为我计划从 REST API 获取 JSON 值。并非 API 中的所有字段都是必填字段。因此,我使用结构字段的指针来帮助我构建 SQL 更新语句,因为:
- 具有 nil 的字段表示未填充(不包括 a
SET name = ?
) - 非零 NullString.Valid == false 表示实际的空值(包括 a
SET name = NULL
) - 并且非零 NullString.Valid == true 表示存在真实的字符串值(包括 a
SET name = ?
)
解决方案
是的,这是因为以下解组规则:
要将 JSON 解组为指针,Unmarshal 首先处理 JSON 为 JSON 文字 null 的情况。在这种情况下,Unmarshal 将指针设置为 nil。否则,Unmarshal 将 JSON 解组为指针指向的值。
我建议做的是添加一个Set
在触发 UnmarshalJSON 时更改为 true 的字段(如果有任何值,保证会被触发),然后将其更改*NullString
为 simple NullString
,如下所示:
package main
import (
"database/sql"
"encoding/json"
"log"
)
// NullString
type NullString struct {
Set bool
sql.NullString
}
func (n *NullString) UnmarshalJSON(b []byte) error {
n.Set = true
n.Valid = string(b) != "null"
e := json.Unmarshal(b, &n.String)
return e
}
type Person struct {
Name NullString `json:"name"`
}
func BuildUpdateSQL(jsonString string) string {
p := Person{}
e := json.Unmarshal([]byte(jsonString), &p)
if e != nil {
log.Println(e)
}
log.Printf("%#v", p)
return ""
}
func main() {
BuildUpdateSQL(`{"field_not_exist":"samantha"}`)
BuildUpdateSQL(`{"name":"samantha"}`)
BuildUpdateSQL(`{"name":null}`)
}
推荐阅读
- html - 如何在不移动选项图标的情况下向右浮动收件箱
- azure - Azure Devop Pipelines:是否可以在发布期间(或作为发布的最后一步)自动修改部署组代理的标签?
- websocket - 为什么 python websockets 客户端每 50 秒重置一次连接?
- python - 调用 `logging` 会干扰其他模块
- docker - azure管道中dockerfile中复制命令的路径错误
- r - 如何在R中的折线图中添加第二个x轴
- android - 安装后使用初始“应用程序启动”URL 中的附加参数启动移动应用程序
- android - 当 ViewHolder 到达 RecyclerView 的顶部或底部时如何停止拖动
- rust - 如何跨多个微服务共享 .proto 消息?
- javascript - 如何使用 .get() 方法从 javascript 嵌套对象中获取属性