programing

이동에서 json을 표시하지 않음: 필수 필드입니까?

lastmemo 2023. 2. 25. 19:42
반응형

이동에서 json을 표시하지 않음: 필수 필드입니까?

Go를 사용하여 JSON 입력을 해석할 때 필드를 찾을 수 없는 경우 오류가 발생할 수 있습니까?

나는 서류에서 그것을 찾을 수 없었다.

필요에 따라 필드를 지정하는 태그가 있습니까?

에 태그가 없습니다.encoding/json필드를 "required"로 설정하는 패키지.직접 쓰거나 둘 중 하나일 것입니다.MarshalJSON()method 또는 post check를 실행하여 누락된 필드를 확인합니다.

결측 필드를 확인하려면 포인터를 사용하여 결측값/늘값과 제로값을 구분해야 합니다.

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)
}

놀이터.

또한 필드를 포인터로 만들지 않고도 특정 유형(즉, 몇 개의 json 레이어에 포함된 필수 필드)에 대한 언마셜링을 재정의할 수 있습니다.언마샬JSON은 Unmarshaler 인터페이스에 의해 정의됩니다.

type EnumItem struct {                                                                                            
    Named                                                                                                         
    Value string                                                                                                  
}                                                                                                                 

func (item *EnumItem) UnmarshalJSON(data []byte) (err error) {                                                    
    required := struct {                                                                                          
        Value *string `json:"value"`                                                                              
    }{}                                                                                                           
    all := struct {                                                                                               
        Named                                                                                                     
        Value string `json:"value"`                                                                               
    }{}                                                                                                           
    err = json.Unmarshal(data, &required)                                                                         
    if err != nil {                                                                                               
        return                                                                                                    
    } else if required.Value == nil {                                                                             
        err = fmt.Errorf("Required field for EnumItem missing")                                                   
    } else {                                                                                                      
        err = json.Unmarshal(data, &all)                                                                          
        item.Named = all.Named                                                                                    
        item.Value = all.Value                                                                                    
    }                                                                                                             
    return                                                                                                        
}                                                       

커스터마이즈된 것을 체크하는 또 다른 방법이 있습니다.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

플레이그라운드로 이동하여 완성된 코드를 확인하실 수 있습니다.

Unmarshaler 인터페이스를 구현하기만 하면 JSON의 성능 저하를 해소하는 방법을 커스터마이즈할 수 있습니다.

JSON 스키마 검증을 사용할 수도 있습니다.

package main

import (
    "encoding/json"
    "fmt"

    "github.com/alecthomas/jsonschema"
    "github.com/xeipuuv/gojsonschema"
)

type Bird struct {
    Species     string `json:"birdType"`
    Description string `json:"what it does" jsonschema:"required"`
}

func main() {
    var bird Bird
    sc := jsonschema.Reflect(&bird)
    b, _ := json.Marshal(sc)

    fmt.Println(string(b))

    loader := gojsonschema.NewStringLoader(string(b))
    documentLoader := gojsonschema.NewStringLoader(`{"birdType": "pigeon"}`)

    schema, err := gojsonschema.NewSchema(loader)
    if err != nil {
        panic("nop")
    }
    result, err := schema.Validate(documentLoader)
    if err != nil {
        panic("nop")
    }

    if result.Valid() {
        fmt.Printf("The document is valid\n")
    } else {
        fmt.Printf("The document is not valid. see errors :\n")
        for _, err := range result.Errors() {
            // Err implements the ResultError interface
            fmt.Printf("- %s\n", err)
        }
    }

}

출력

{"$schema":"http://json-schema.org/draft-04/schema#","$ref":"#/definitions/Bird","definitions":{"Bird":{"required":["birdType","what it does"],"properties":{"birdType":{"type":"string"},"what it does":{"type":"string"}},"additionalProperties":false,"type":"object"}}}
The document is not valid. see errors :
- (root): what it does is required

Strict JSON 해석에서 가져온 코드 예시

언급URL : https://stackoverflow.com/questions/19633763/unmarshaling-json-in-go-required-field

반응형