简体   繁体   English

您如何编组 sql.NullString 以使 output 展平以仅给出 go 中的值?

[英]How do you marshal a sql.NullString such that the output is flattened to give just the value in go?

Given a go struct给定一个 go 结构

type Company struct {
    ID   int             `json:"id"`              
    Abn  sql.NullString  `json:"abn,string"`
}

when marshalled with something like this当用这样的东西编组时

company := &Company{}
company.ID = 68
company.Abn = "SomeABN"
result, err := json.Marshal(company)

the result is结果是

{
    "id": "68",
    "abn": {
        "String": "SomeABN",
        "Valid": true
    }
}

The result desired is想要的结果是

{
    "id": "68",
    "abn": "SomeABN"
}

I've tried explicitly stating that Abn is a string.我试过明确说明 Abn 是一个字符串。

Abn  sql.NullString  `json:"abn,string"`

which did not change the result.这并没有改变结果。

How do you marshal a sql.NullString such that the output is flattened to give just the value in go?您如何编组 sql.NullString 以使 output 展平以仅给出 go 中的值?

EDIT编辑

Something like I ended up with after reading the answers from https://stackoverflow.com/users/8256506/nilsocket and https://stackoverflow.com/users/965900/mkopriva在阅读https://stackoverflow.com/users/8256506/nilsockethttps://stackoverflow.com/users/965900/mkopriva的答案后,我得到了类似的结果

package main

import (
    "database/sql"
    "encoding/json"
    "reflect"
    //"github.com/lib/pq"
)

/*
    https://medium.com/aubergine-solutions/how-i-handled-null-possible-values-from-database-rows-in-golang-521fb0ee267
*/

type NullString sql.NullString

func (x *NullString) MarshalJSON() ([]byte, error) {
    if !x.Valid {
        x.Valid = true
        x.String = ""
        //return []byte("null"), nil
    }
    return json.Marshal(x.String)
}

// Scan implements the Scanner interface for NullString
func (ns *NullString) Scan(value interface{}) error {
    var s sql.NullString
    if err := s.Scan(value); err != nil {
        return err
    }

    // if nil then make Valid false
    if reflect.TypeOf(value) == nil {
        *ns = NullString{s.String, false}
    } else {
        *ns = NullString{s.String, true}
    }

    return nil
}

type Company struct {
    ID                     int             `json:"id"`    
    Abn                    NullString      `json:"abn"`         
}

You cannot, at least not using just sql.NullString and encoding/json .你不能,至少不能只使用sql.NullStringencoding/json

What you can do is to declare a custom type that embeds sql.NullString and have that custom type implement the json.Marshaler interface.您可以做的是声明一个嵌入sql.NullString的自定义类型,并让该自定义类型实现json.Marshaler接口。

type MyNullString struct {
    sql.NullString
}

func (s MyNullString) MarshalJSON() ([]byte, error) {
    if s.Valid {
        return json.Marshal(s.String)
    }
    return []byte(`null`), nil
}

type Company struct {
    ID   int          `json:"id"`              
    Abn  MyNullString `json:"abn,string"`
}

https://play.golang.org/p/Ak_D6QgIzLb https://play.golang.org/p/Ak_D6QgIzLb

Here is the code,这是代码,

package main

import (
    "database/sql"
    "encoding/json"
    "fmt"
    "log"
)

//Company details
type Company struct {
    ID  int        `json:"id"`
    Abn NullString `json:"abn"`
}

//NullString is a wrapper around sql.NullString
type NullString sql.NullString

//MarshalJSON method is called by json.Marshal,
//whenever it is of type NullString
func (x *NullString) MarshalJSON() ([]byte, error) {
    if !x.Valid {
        return []byte("null"), nil
    }
    return json.Marshal(x.String)
}

func main() {
    company := &Company{}
    company.ID = 68
    //create new NullString value
    nStr := sql.NullString{String: "hello", Valid: true}
    //cast it
    company.Abn = NullString(nStr)
    result, err := json.Marshal(company)
    if err != nil {
        log.Println(err)
    }
    fmt.Println(string(result))
}

Here is the blog post which explains it in detail. 是详细解释它的博客文章。

The question suggests that you want to expose your database structure as JSON (presumably REST-ish) API.该问题表明您希望将数据库结构公开为 JSON(大概是 REST-ish)API。 Unless the project is going to have a short lifespan or the logic layer is trivial, such an approach is considered an antipattern.除非项目的生命周期很短或逻辑层是微不足道的,否则这种方法被认为是反模式。 The internals (database structure) become coupled with the external interface (API) and may result in a high cost of making a change.内部(数据库结构)与外部接口 (API) 耦合在一起,可能会导致进行更改的成本很高。

I'm attaching some reads as Google is full of tutorials on how to do the opposite:我附上了一些读物,因为谷歌有很多关于如何做相反的教程:

https://lostechies.com/jimmybogard/2016/05/12/entities-arent-resources-resources-arent-representations/ https://lostechies.com/jimmybogard/2016/05/12/entities-arent-resources-resources-arent-representations/

https://thorben-janssen.com/dont-expose-entities-in-api/ https://thorben-janssen.com/dont-expose-entities-in-api/

Another option is to use *string instead of sql.NullString另一种选择是使用*string代替sql.NullString

type Company struct {
    ID   int      `json:"id"`              
    Abn  *string  `json:"abn"`
}

Now you may ask yourself what is the Difference between *string and sql.NullString现在你可能会问自己*string 和 sql.NullString 有什么区别

There's no effective difference.没有有效的区别。 We thought people might want to use NullString because it is so common and perhaps expresses the intent more clearly than *string.我们认为人们可能想要使用 NullString,因为它很常见,并且可能比 *string 更清楚地表达了意图。 But either will work.但两者都行。 -- Russ Cox https://groups.google.com/g/golang-nuts/c/vOTFu2SMNeA/m/GB5v3JPSsicJ -- 拉斯考克斯https://groups.google.com/g/golang-nuts/c/vOTFu2SMNeA/m/GB5v3JPSsicJ

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 (SQL)您如何 select 一个最大浮点值以及查询中的其他数据类型值? - (SQL) How do you select a max float value along with other datatypes values within a query? NAT 网关-您 go 如何通过 SSH 进入私有 EC2? - NAT Gateways-how do you go about SSH'ing into the private EC2? 在 Google BigQuery SQL 中,当左连接到另一个表时,如何找到特定列的最小值? - How do you pull find the min value of a specific column, when left joined to another table, in Google BigQuery SQL? 你如何指示 Azure DevOps 将你的 output 放在目标应用服务上的特定位置? - How do you direct Azure DevOps to place your output in a specific location on the target App Service? 您如何使用 terraform 应用程序的 output 作为另一个 terraform 变量的输入? - How do you use the output of a terraform apply as input into another terraform variable? 使用 Textract,如何通过 .py 脚本将 pdf 文件中的表格和 output 表格提取到 csv 文件中? - Using Textract, how do you extract tables from a pdf file and output it into a csv file via .py script? DynamoDB / marshal 函数抱怨未定义的值 - DynamoDB / marshal function complains about an undefined value 如何在 GCP 中为 secret 赋予角色? - How do I give a role to secret in GCP? 如何从 SQL 的另一行中取最小值? - How do I take the minimum value from another row in SQL? 如何从谷歌云 sql 实例中只恢复数据库而不是用户 - How do I restore just the databases and not the users from a google cloud sql instance
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM