2013-07-01 23 views
10

Tôi đã thử voluptuousschema, cả hai đều đơn giản và tuyệt vời trong xác thực, nhưng cả hai đều thực hiện báo cáo lỗi dựa trên ngoại lệ, tức là chúng không thành công do lỗi đầu tiên. Có cách nào tôi có thể nhận được tất cả các lỗi xác nhận dữ liệu trong Voluptuous hoặc Schema?Thư viện xác thực python đơn giản báo cáo tất cả các lỗi xác thực thay vì lỗi đầu tiên?

Tôi tìm thấy jsonschema dường như phù hợp với một số yêu cầu, nhưng không có xác thực cho khóa đối tượng và xác thực dựa trên chức năng tùy chỉnh (ví dụ: lambdas).

Yêu cầu:

def myMethod(input_dict): 

    #input_dict should abide to this schema -> 
    # { 'id' : INT , 'name':'string 5-10 chars','hobbies': LIST OF STRINGS } 
    # for incorrect input like 
    # {'id': 'hello','name':'Dhruv','hobbies':[1,2,3] } 
    # I should be able to return all errors like 
    # ['id' is not integer,'hobbies' is not list of strings ] 
+0

Bạn có thể đưa ra ví dụ về những gì bạn cần từ thư viện như vậy không? Nếu xác thực không thành công và bạn muốn tiếp tục và không dừng thực thi, nó giống như một công việc để ghi nhật ký. –

+0

@BurhanKhalid Chắc chắn, những gì tôi muốn xác nhận đầu vào của phương thức và trả về tất cả các lỗi xác nhận. – DhruvPathak

+0

https://pypi.python.org/pypi/voluptuous#error-reporting dường như đang nói rằng nếu trình xác thực của bạn tăng các trường hợp ngoại lệ 'Không hợp lệ ', chúng sẽ bị bắt và liên kết với một đường dẫn. Liệu nó không làm những gì bạn muốn? (Tôi chỉ tò mò, tôi không bao giờ sử dụng nó) – rectummelancolique

Trả lời

1

Tôi đã sử dụng jsonschema trước và nó là chính xác có thể làm những gì bạn muốn nó làm. Báo cáo lỗi dựa trên ngoại lệ nếu bạn muốn, nhưng bạn cũng có thể lặp qua tất cả các lỗi xác thực được tìm thấy trong tài liệu, tôi đã viết một chương trình ví dụ ngắn sử dụng lược đồ của bạn (xem Json Schema V3 Spec) và in ra tất cả các lỗi tìm thấy.

Chỉnh sửa: Tôi đã thay đổi tập lệnh để bây giờ nó sử dụng trình xác thực tùy chỉnh cho phép bạn cuộn xác thực của riêng mình, mã phải tự giải thích. Bạn có thể tra cứu nguồn jsonschema cho các thông tin trên extend và cách các trình xác thực được mở rộng/mã hóa.

#!/usr/bin/env python2 

from jsonschema import Draft3Validator 
from jsonschema.exceptions import ValidationError 
from jsonschema.validators import extend 
import json 
import sys 

schema = { 
    "type": "object", 
    "required": True, 
    "additinalProperties": False, 
    "properties": { 
     "id": { 
      "type": "integer", 
      "required": True 
     }, 
     "name": { 
      "type": "string", 
      "required": True, 
      "minLength": 5, 
      "maxLength": 10 
     }, 
     "hobbies": { 
      "type": "array", 
      "customvalidator": "hobbies", 
      "required": True, 
      "items": { 
       "type": "string" 
      } 
     } 
    } 
} 


def hobbiesValidator(validator, value, instance, schema): 
    if 'Foo' not in instance: 
     yield ValidationError("You need to like Foo") 

    for field in instance: 
     if not validator.is_type(instance, "string"): 
      yield ValidationError("A hobby needs to be a string") 
     elif len(field) < 5: 
      err = "I like only hobbies which are len() >= 5, {} doesn't" 
      yield ValidationError(err.format(value)) 


def anotherHobbiesValidator(validator, value, instance, schema): 
    pass 


myCustomValidators = { 
    'hobbies': hobbiesValidator, 
    'anotherHobbies': anotherHobbiesValidator 
} 


def customValidatorDispatch(validator, value, instance, schema): 
    if value not in myCustomValidators: 
     err = '{} is unknown, we only know about: {}' 
     yield ValidationError(err.format(value, ', '.join(myCustomValidators.keys()))) 
    else: 
     errors = myCustomValidators[value](validator, value, instance, schema) 
     for error in errors: 
      yield error 


def myMethod(input_dict): 
    customValidator = extend(Draft3Validator, {'customvalidator': customValidatorDispatch}, 'MySchema') 
    validator = customValidator(schema) 

    errors = [e for e in validator.iter_errors(input_dict)] 
    if len(errors): 
     return errors 

    # do further processing here 
    return [] 

if __name__ == '__main__': 
    data = None 
    try: 
     f = open(sys.argv[1], 'r') 
     data = json.loads(f.read()) 
    except Exception, e: 
     print "Failed to parse input: {}".format(e) 
     sys.exit(-1) 

    errors = myMethod(data) 

    if not len(errors): 
     print "Input is valid!" 
    else: 
     print "Input is not valid, errors:" 
     for error in errors: 
      print "Err: ", error 

đầu vào không hợp lệ:

$ cat invalid-input.json 
{ 
    "id": "hello", 
    "name": "Dhruv", 
    "hobbies": [ 
     1, 2, 3 
    ] 
} 

$ ./validate.py invalid-input.json 
Input is not valid, errors: 
Err: 1 is not of type 'string' 

Failed validating 'type' in schema['properties']['hobbies']['items']: 
    {'type': 'string'} 

On instance['hobbies'][0]: 
    1 
Err: 2 is not of type 'string' 

Failed validating 'type' in schema['properties']['hobbies']['items']: 
    {'type': 'string'} 

On instance['hobbies'][1]: 
    2 
Err: 3 is not of type 'string' 

Failed validating 'type' in schema['properties']['hobbies']['items']: 
    {'type': 'string'} 

On instance['hobbies'][2]: 
    3 
Err: You need to like Foo 

Failed validating 'customvalidator' in schema['properties']['hobbies']: 
    {'customvalidator': 'hobbies', 
    'items': {'type': 'string'}, 
    'required': True, 
    'type': 'array'} 

On instance['hobbies']: 
    [1, 2, 3] 
Err: A hobby needs to be a string 

Failed validating 'customvalidator' in schema['properties']['hobbies']: 
    {'customvalidator': 'hobbies', 
    'items': {'type': 'string'}, 
    'required': True, 
    'type': 'array'} 

On instance['hobbies']: 
    [1, 2, 3] 
Err: A hobby needs to be a string 

Failed validating 'customvalidator' in schema['properties']['hobbies']: 
    {'customvalidator': 'hobbies', 
    'items': {'type': 'string'}, 
    'required': True, 
    'type': 'array'} 

On instance['hobbies']: 
    [1, 2, 3] 
Err: A hobby needs to be a string 

Failed validating 'customvalidator' in schema['properties']['hobbies']: 
    {'customvalidator': 'hobbies', 
    'items': {'type': 'string'}, 
    'required': True, 
    'type': 'array'} 

On instance['hobbies']: 
    [1, 2, 3] 
Err: u'hello' is not of type 'integer' 

Failed validating 'type' in schema['properties']['id']: 
    {'required': True, 'type': 'integer'} 

On instance['id']: 
    u'hello' 

Tôi nghĩ rằng yêu cầu của bạn bây giờ được lấp đầy bởi kịch bản này.

+0

nhưng jsonschema không đáp ứng các yêu cầu như đã đề cập trong câu hỏi "không có xác nhận cho các khóa đối tượng, và xác nhận dựa trên chức năng tùy chỉnh (ví dụ lambdas)." – DhruvPathak

+0

Tôi đã thêm xác thực tùy chỉnh vào mã của mình, bây giờ nó sẽ làm những gì bạn muốn (khi bạn triển khai lược đồ và trình duyệt tính hợp lệ của riêng mình). – Luminger

11

Thực tế, Voluptuous không cung cấp chức năng này, mặc dù không rõ ràng trong tài liệu, nó chỉ đơn giản là gọi đến MultipleInvalid.errors. Hàm trả về một danh sách các trường hợp ngoại lệ bắt buộc của bạn là Invalid.

ví dụ:

try: 

    schema({...}) 

except MultipleInvalid as e: 
    # get the list of all `Invalid` exceptions caught 
    print e.errors 
+0

Cảm ơn, sẽ thử điều này và xem nó có hoạt động không. Nó sẽ là tốt nếu nó hoạt động theo cách này, như voluptous là linh hoạt hơn jsonschema. – DhruvPathak

+0

bạn đã thử chưa? :) – chutsu

+0

Vâng, nó hoạt động. Cảm ơn! – Kevin

Các vấn đề liên quan