Go 自定义构建的JSON架构未正确验证
我有一个定制的JSON模式,它只有几个顶层。这里的问题是,它不能100%验证所有内容。例如,它只检测4个字段中的2个,必填字段根本不起作用,additionalproperties也不起作用,等等。我正在使用json模式Go 自定义构建的JSON架构未正确验证,go,jsonschema,Go,Jsonschema,我有一个定制的JSON模式,它只有几个顶层。这里的问题是,它不能100%验证所有内容。例如,它只检测4个字段中的2个,必填字段根本不起作用,additionalproperties也不起作用,等等。我正在使用json模式 { "users": { "PUT": { "definitions": {}, "$schema": "http://json-schema.org/draft-07/schema#", "$
{
"users": {
"PUT": {
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/root.json",
"type": "object",
"title": "The Root Schema",
"required": [
"DisplayName",
"Username",
"Email",
"Password"
],
"properties": {
"DisplayName": {
"$id": "#/properties/DisplayName",
"type": "string",
"title": "The Displayname Schema",
"default": "",
"examples": [
""
],
"minLength": 3,
"maxLength": 24,
"pattern": "^(.*)$"
},
"Username": {
"$id": "#/properties/Username",
"type": "string",
"title": "The Username Schema",
"default": "",
"examples": [
""
],
"minLength": 3,
"maxLength": 15,
"pattern": "^(.*)$"
},
"Email": {
"$id": "#/properties/Email",
"type": "string",
"title": "The Email Schema",
"default": "",
"examples": [
""
],
"minLength": 7,
"pattern": "^(.*)$",
"format": "email"
},
"Password": {
"$id": "#/properties/Password",
"type": "string",
"title": "The Password Schema",
"default": "",
"examples": [
""
],
"pattern": "^(.*)$"
}
},
"additionalProperties": false
}
}
}
我正在解析所有内容,如下所示:
func Validate(data interface{}, r *http.Request) (interface{}, error) {
// Convert the data struct to a readable JSON bytes
JSONparams, err := json.Marshal(data)
if err != nil {
return nil, err
}
// Split URL segments so we know what part of the API they are accessing
modules := strings.Split(r.URL.String(), "/")
modules = modules[(len(modules) - 1):]
// Read the schema file
fileSchema, _ := ioutil.ReadFile("config/schema/schema.json")
var object interface{}
// Unmarshal it so we can choose what schema we specifically want
err = json.Unmarshal(fileSchema, &object)
if err != nil {
log.Fatal(err)
}
// Choose the preferred schema
encodedJSON, err := json.Marshal(object.(map[string]interface{})[strings.Join(modules, "") + "s"].(map[string]interface{})[r.Method])
if err != nil {
log.Fatal(err)
}
// Load the JSON schema
schema := gojsonschema.NewStringLoader(string(encodedJSON))
// Load the JSON params
document := gojsonschema.NewStringLoader(string(JSONparams))
// Validate the document
result, err := gojsonschema.Validate(schema, document)
if err != nil {
return nil, err
}
if !result.Valid() {
// Map the errors into a new array
var errors = make(map[string]string)
for _, err := range result.Errors() {
errors[err.Field()] = err.Description()
}
// Convert the array to an interface that we can convert to JSON
resultMap := map[string]interface{}{
"success": false,
"result": map[string]interface{}{},
"errors": errors,
}
// Convert the interface to a JSON object
errorObject, err := json.Marshal(resultMap)
if err != nil {
return nil, err
}
return errorObject, nil
}
return nil, nil
}
type CreateParams struct {
DisplayName string
Username string
Email string
Password string
}
var (
response interface{}
status int = 0
)
func Create(w http.ResponseWriter, r *http.Request) {
status = 0
// Parse the request so we can access the query parameters
r.ParseForm()
// Assign them to the interface variables
data := &CreateParams{
DisplayName: r.Form.Get("DisplayName"),
Username: r.Form.Get("Username"),
Email: r.Form.Get("Email"),
Password: r.Form.Get("Password"),
}
// Validate the JSON data
errors, err := schema.Validate(data, r)
if err != nil {
responseJSON := map[string]interface{}{
"success": false,
"result": map[string]interface{}{},
}
log.Fatal(err.Error())
response, err = json.Marshal(responseJSON)
status = http.StatusInternalServerError
}
// Catch any errors generated by the validator and assign them to the response interface
if errors != nil {
response = errors
status = http.StatusBadRequest
}
// Status has not been set yet, so it's safe to assume that everything went fine
if status == 0 {
responseJSON := map[string]interface{}{
"success": true,
"result": map[string]interface{} {
"DisplayName": data.DisplayName,
"Username": data.Username,
"Email": data.Email,
"Password": nil,
},
}
response, err = json.Marshal(responseJSON)
status = http.StatusOK
}
// We are going to respond with JSON, so set the appropriate header
w.Header().Set("Content-Type", "application/json")
// Write the header and the response
w.WriteHeader(status)
w.Write(response.([]byte))
}
我这样做的原因是我正在构建一个restapi,如果API/auth/user
获得一个PUT请求,我希望能够使用PUT方法指定特定“用户”部分的数据需求
你知道如何做到这一点吗
编辑:
我的json数据:
{
"DisplayName": "1234",
"Username": "1234",
"Email": "test@gmail.com",
"Password": "123456"
}
编辑2:
此数据应与架构一起失败
{
"DisplayName": "1", // min length is 3
"Username": "", // this field is required but is empty here
"Email": "testgmail.com", // not following the email format
"Password": "123456111111111111111111111111111111111111111111111" // too long
}
如果我使用
gojsonschema
手动加载模式和数据,它将按预期工作。我怀疑,由于加载模式的方式有点复杂,因此输入的模式最终会与您预期的有所不同,但由于您的代码示例都是基于HTTP的,所以我无法亲自进行测试。Hi!如果您提供要验证的完整JSON模式和完整JSON实例数据,我将能够提供最好的帮助。我不熟悉go,但我可以很容易地告诉您是否存在架构问题。@Relequestual我已经用完整的架构和JSON数据更新了帖子。谢谢。我已经使用测试了您的模式和数据。您可以删除模式
、默认值
和示例
,它们在这里什么都不做。此外,您不需要为每个字段指定$id
。我能够使按要求
按预期工作。我还能够使每个字段都无法通过验证。我认为您可能期望JSON模式做一些它没有做的事情。您能提供您预期验证失败的JSON数据的示例吗?@Relequestual Updated。我还想指出,在尝试您提供的架构验证器时,required似乎不会覆盖参数的最小长度规则。我不确定required
将如何覆盖min length
。Required只意味着对象键必须存在,并且没有指定任何关于其值的内容。在您的示例中,应该失败:在您的模式中,“Password”没有设置最小长度。“用户名”和“显示名称”按预期失败,未满足最小长度。对于“格式”,对它们的支持是可选的,并且取决于每个实现。我最后打印了模式的值,并在模式验证器中使用了它,在那里它工作得非常好。我想这里肯定还有其他一些错误,你不能用肉眼轻易发现,比如编码问题或其他什么?我为你做了一个快速回复,如果你想自己尝试一下的话:问题是你从表单中获取值,将它们放在一个结构中,然后将该结构转换为JSON。如果表单中的所有值都为空,这仍然会导致以下JSON:{“DisplayName”:““Username”:”、“Email”:““Password”:”}
这意味着所有属性都存在,它们只是空的,因此所需的检查将通过,密码实际上是有效的,因为它通过了regex^(.*)$
。您应该在struct字段中指定json:ommitempty
,以删除空字段。感谢您的帮助。我想知道这是否真的意味着任何不同,这回答了我的问题。