将 json null 解组为 NullString 的指针

我无法将json.Unmarshalnull 值放入*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 值。但是当我传入一个空的 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 = ?)


阿晨1998
浏览 119回答 1
1回答

慕桂英3389331

是的,这是因为以下解组规则:要将 JSON 解组为指针,Unmarshal 首先处理 JSON 为 JSON 文字 null 的情况。在这种情况下,Unmarshal 将指针设置为 nil。否则,Unmarshal 将 JSON 解组为指针指向的值。我建议做的是添加一个Set字段,该字段在 UnmarshalJSON 被触发时更改为 true(如果有任何值,则保证被触发),然后将 更改*NullString为简单的NullString,如下所示:package mainimport (    "database/sql"    "encoding/json"    "log")// NullStringtype 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}`)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go