Golang的解组json:必填字段?

时间:2013-10-28 11:35:54

标签: json go

如果在Golang中解组时在json中找不到字段,是否可能生成错误?我在文档中找不到它。是否有任何标签指定所需的字段?

4 个答案:

答案 0 :(得分:52)

encoding/json包中没有标记将字段设置为“required”。您将需要编写自己的MarshalJSON()方法,或对缺少的字段进行检查。

要检查缺少的字段,您必须使用指针来区分missing / null和zero值:

type JsonStruct struct {
    String *string
    Number *float64
}

完整的工作示例:

package main

import (
    "fmt"
    "encoding/json"
)

type JsonStruct struct {
    String *string
    Number *float64
}

var rawJson = []byte(`{
    "string":"We do not provide a number"
}`)


func main() {
    var s *JsonStruct
    err := json.Unmarshal(rawJson, &s)
    if err != nil {
        panic(err)
    }

    if s.String == nil {
        panic("String is missing or null!")
    }

    if s.Number == nil {
        panic("Number is missing or null!")
    }

    fmt.Printf("String: %s  Number: %f\n", *s.String, *s.Number)
}

Playground

答案 1 :(得分:5)

您还可以覆盖特定类型的解组(以便隐藏在几个json图层中的必填字段),而不必将该字段设为指针。

SELECT w.well_id,
w.WELL_NR,
w.WELL_NM,
w.WELL_API_NR,
ws.WELL_SGMNT_SIDE_TRCK_CD,
wc.WELL_CMPLTN_CD,
wc.WELL_SGMNT_ID,
wc.WELL_CMPLTN_ID
FROM WELL W
JOIN WELL_SGMNT ws
ON ws.well_id=w.well_id
JOIN WELL_CMPLTN wc
ON ws.WELL_SGMNT_ID=wc.WELL_SGMNT_ID
WHERE w.well_id ='13030' AND wc.WELL_CMPLTN_ID = 
(SELECT MAX(wc.WELL_CMPLTN_ID) 
    FROM WELL W
    JOIN WELL_SGMNT ws
    ON ws.well_id=w.well_id
    JOIN WELL_CMPLTN wc
    ON ws.WELL_SGMNT_ID=wc.WELL_SGMNT_ID
    WHERE w.well_id ='13030'
)

答案 2 :(得分:3)

您只需实现Unmarshaler接口即可自定义JSON的解组方式。

答案 3 :(得分:0)

这是检查自定义的tag

的另一种方法

您可以像这样为您的结构创建标签:

type Profile struct {
    Name string `yourprojectname:"required"`
    Age  int
}

使用reflect检查代码是否分配了required

func (p *Profile) Unmarshal(data []byte) error {
    err := json.Unmarshal(data, p)
    if err != nil {
        return err
    }

    fields := reflect.ValueOf(p).Elem()
    for i := 0; i < fields.NumField(); i++ {

        yourpojectTags := fields.Type().Field(i).Tag.Get("yourprojectname")
        if strings.Contains(yourpojectTags, "required") && fields.Field(i).IsZero() {
            return errors.New("required field is missing")
        }

    }
    return nil
}

测试用例如下:

func main() {

    profile1 := `{"Name":"foo", "Age":20}`
    profile2 := `{"Name":"", "Age":21}`

    var profile Profile

    err := profile.Unmarshal([]byte(profile1))
    if err != nil {
        log.Printf("profile1 unmarshal error: %s\n", err.Error())
        return
    }
    fmt.Printf("profile1 unmarshal: %v\n", profile)

    err = profile.Unmarshal([]byte(profile2))
    if err != nil {
        log.Printf("profile2 unmarshal error: %s\n", err.Error())
        return
    }
    fmt.Printf("profile2 unmarshal: %v\n", profile)

}

结果:

profile1 unmarshal: {foo 20}

2009/11/10 23:00:00 profile2 unmarshal error: required field is missing

您可以转到Playground查看完成的代码