将 JSON 数组解组为指针切片时跳过空值

我有以下结构:


type Item struct {

    Id       string     `json:"id"`

    Name     string     `json:"name"`

    Products []*Product `json:"products"`

}


func (i *Item) Transform(input []byte) error {

    return json.Unmarshal(input, i)

}

Products我必须对它的成员和它的嵌套成员执行多项操作,例如[]*Variant{}or[]*Shipping{}等。


因为结构中的大部分切片Item都是指针切片,所以我处理这些数据的代码如下所示:


for _, product := range i.Products {

    if product == nil {

        continue

    }

    

    for _, variant := range product.Variants {

        if variant == nil {

            continue

        }

        

        for _, shipping := range shippings {

            if shipping == nil {

                continue

            }

      

            // and so on...

        }

    }

}

有什么方法可以模仿指针切片中的值吗omitempty?nil下面的例子。


JSON 输入:


{

    "products": [

        null,

        {},

        null

    ]

}

输出,相当于:


input := Item{

    Products: []Product{ {} }, // without nulls

}


我尝试使用omitemptyon[]*Property但它不起作用。我还尝试使用非指针值,但随后 Go 将每个 null 初始化为默认结构值。


千万里不及你
浏览 75回答 1
1回答

慕田峪9158850

您可以实施自定义json.Unmarshaler.type Item struct {    Id       string      `json:"id"`    Name     string      `json:"name"`    Products ProductList `json:"products"`}// Use []*Product if you intend to modify// the individual elements in the slice.// Use []Product if the elements are read-only.type ProductList []*Product// Implememt the json.Unmarshaler interface.// This will cause the encoding/json decoder to// invoke the UnmarshalJSON method, instead of// performing the default decoding, whenever it// encounters a ProductList instance.func (ls *ProductList) UnmarshalJSON(data []byte) error {    // first, do a normal unmarshal    pp := []*Product{}    if err := json.Unmarshal(data, &pp); err != nil {        return err    }    // next, append only the non-nil values    for _, p := range pp {        if p != nil {            *ls = append(*ls, p)        }    }    // done    return nil}[]*Variant{}使用 Go1.18及更高版本,您不必为其他[]*Shipping{}类型实现自定义解组。相反,您可以使用带有元素类型参数的切片类型。type SkipNullList[T any] []*Tfunc (ls *SkipNullList[T]) UnmarshalJSON(data []byte) error {    pp := []*T{}    if err := json.Unmarshal(data, &pp); err != nil {        return err    }    for _, p := range pp {        if p != nil {            *ls = append(*ls, p)        }    }    return nil}type Item struct {    Id       string                `json:"id"`    Name     string                `json:"name"`    Products SkipNullList[Product] `json:"products"`}type Product struct {    // ...    Variants SkipNullList[Variant] `json:"variants"`}type Variant struct {    // ...    Shippings SkipNullList[Shipping] `json:"shippings"`}https://go.dev/play/p/az_9Mb_RBKX
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go