为了账号安全,请及时绑定邮箱和手机立即绑定

将 json null 解组为 NullString 的指针

将 json null 解组为 NullString 的指针

Go
阿晨1998 2023-04-17 15:20:13
我无法将json.Unmarshalnull 值放入*NullString结构中的字段中。这是我的意思的一个简化示例:package mainimport (  "database/sql"  "encoding/json"  "log")// NullStringtype 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 值。但是当我传入一个空的 json 值时,NullString 解组器似乎甚至没有触发。有人知道我做错了什么吗?背景我尝试这样做的原因是因为我计划从 REST API 获取 JSON 值。并非 API 中的所有字段都是必填字段。因此,我使用结构字段的指针来帮助我构建 SQL Update 语句,因为:带有 nil 的字段表示未填充(不包括SET name = ?)non-nil NullString.Valid == false 表示实际的空值(包括一个SET name = NULL)和非零 NullString.Valid == true 表示存在真实的字符串值(包括 a SET name = ?)
查看完整描述

1 回答

?
慕桂英3389331

TA贡献2036条经验 获得超8个赞

是的,这是因为以下解组规则:

要将 JSON 解组为指针,Unmarshal 首先处理 JSON 为 JSON 文字 null 的情况。在这种情况下,Unmarshal 将指针设置为 nil。否则,Unmarshal 将 JSON 解组为指针指向的值。

我建议做的是添加一个Set字段,该字段在 UnmarshalJSON 被触发时更改为 true(如果有任何值,则保证被触发),然后将 更改*NullString为简单的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}`)

}


查看完整回答
反对 回复 2023-04-17
  • 1 回答
  • 0 关注
  • 118 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信