मैं एक एपीआई से वापस प्राप्त डेटा की अखंडता को सत्यापित करने का सबसे अच्छा तरीका खोजने का प्रयास कर रहा हूं।

उदाहरण के लिए, मेरे पास एक डेटा सेट है जो एक मॉडल (IContact) से मेल खाता है।

डेटा:

{
    'aemBounceBack': False,
    'aemOptOut': False,
    'altEmailAddress': None,
    'alternateCountryCode': None,
    'alternateExtension': None,
    'alternateMaskFormat': None,
    'alternatePhone': None,
    'amaScore': None,
    'birthday': None,
    'businessAddress': {
        'city': None,
        'country': None,
        'latitude': 0.0,
        'line1': None,
        'line2': None,
        'line3': None,
        'longitude': 0.0,
        'postalCode': None,
        'state': None},
    'businessCountryCode': None,
    'businessExtension': None,
    'businessMaskFormat': None,
    'businessPhone': None,
    'company': None,
    'companyID': '',
    'contactType': 'User',
    'created': '2020-03-20T03:36:51+00:00',
    'customFields': {
        'spouse': None,
        'user1': None,
        'user10': None,
        'user2': None,
        'user3': None,
        'user4': None,
        'user5': None,
        'user6': None,
        'user7': None,
        'user8': None,
        'user9': None
    },
    'department': None,
    'edited': '2020-03-26T00:36:12+00:00',
    'editedBy': 'Admin',
    'emailAddress': None,
    'faxCountryCode': None,
    'faxExtension': None,
    'faxMaskFormat': None,
    'faxPhone': None,
    'firstName': '',
    'fullName': 'Admin',
    'homeAddress': {
        'city': None,
        'country': None,
        'latitude': 0.0,
        'line1': None,
        'line2': None,
        'line3': None,
        'longitude': 0.0,
        'postalCode': None,
        'state': None
    },
    'homeCountryCode': None,
    'homeExtension': None,
    'homeMaskFormat': None,
    'homePhone': None,
    'id': '0a7e183d-7e72-4d68-87a3-478bdbbd2356',
    'idStatus': None,
    'importDate': None,
    'isFavorite': 'False',
    'isImported': False,
    'isPrivate': False,
    'isUser': True,
    'jobTitle': None,
    'lastAttempt': None,
    'lastEmail': None,
    'lastLetterSent': None,
    'lastMeeting': None,
    'lastName': 'Admin',
    'lastReach': '2020-03-25T17:30:00+00:00',
    'lastResults': None,
    'latitude': 0.0,
    'longitude': 0.0,
    'messengerID': None,
    'middleName': '',
    'mobileCountryCode': None,
    'mobileExtension': None,
    'mobileMaskFormat': None,
    'mobilePhone': None,
    'namePrefix': '',
    'nameSuffix': '',
    'pagerCountryCode': None,
    'pagerExtension': None,
    'pagerMaskFormat': None,
    'pagerPhone': None,
    'personalEmailAddress': None,
    'recordManager': 'Admin',
    'recordOwner': 'Admin',
    'referredBy': None,
    'salutation': '',
    'website': None
}

मॉडल:

NoneType = type(None)


class IContact:
    id = (NoneType, str)
    idStatus = (NoneType, str)
    isUser = (NoneType, bool)
    company = (NoneType, str)
    department = (NoneType, str)
    companyID = (NoneType, str)
    contactType = (NoneType, str)
    namePrefix = (NoneType, str)
    firstName = (NoneType, str)
    middleName = (NoneType, str)
    lastName = (NoneType, str)
    nameSuffix = (NoneType, str)
    fullName = (NoneType, str)
    isFavorite = (NoneType, str)
    isImported = (NoneType, bool)
    importDate = (NoneType, str)
    isPrivate = (NoneType, bool)
    lastResults = (NoneType, str)
    lastEmail = (NoneType, str)
    lastAttempt = (NoneType, str)
    lastReach = (NoneType, str)
    lastMeeting = (NoneType, str)
    lastLetterSent = (NoneType, str)
    latitude = (NoneType, float)
    longitude = (NoneType, float)
    messengerID = (NoneType, str)
    referredBy = (NoneType, str)
    salutation = (NoneType, str)
    jobTitle = (NoneType, str)
    amaScore = (NoneType, int)
    emailAddress = (NoneType, str)
    altEmailAddress = (NoneType, str)
    personalEmailAddress = (NoneType, str)
    website = (NoneType, str)
    birthday = (NoneType, str)
    businessAddress = (NoneType, dict)
    businessPhone = (NoneType, str)
    businessExtension = (NoneType, str)
    businessCountryCode = (NoneType, int)
    businessMaskFormat = (NoneType, str)
    mobilePhone = (NoneType, str)
    mobileExtension = (NoneType, str)
    mobileCountryCode = (NoneType, int)
    mobileMaskFormat = (NoneType, str)
    faxPhone = (NoneType, str)
    faxExtension = (NoneType, str)
    faxCountryCode = (NoneType, int)
    faxMaskFormat = (NoneType, str)
    homeAddress = (NoneType, dict)
    homePhone = (NoneType, str)
    homeExtension = (NoneType, str)
    homeCountryCode = (NoneType, int)
    homeMaskFormat = (NoneType, str)
    alternatePhone = (NoneType, str)
    alternateExtension = (NoneType, str)
    alternateCountryCode = (NoneType, int)
    alternateMaskFormat = (NoneType, str)
    pagerPhone = (NoneType, str)
    pagerExtension = (NoneType, str)
    pagerCountryCode = (NoneType, int)
    pagerMaskFormat = (NoneType, str)
    aemOptOut = (NoneType, bool)
    aemBounceBack = (NoneType, bool)
    customFields = (NoneType, object)
    created = (NoneType, str)
    edited = (NoneType, str)
    editedBy = (NoneType, str)
    recordOwner = (NoneType, str)
    recordManager = (NoneType, str)

मेरे परीक्षणों में मैं एपीआई (जेसन) से प्राप्त चाबियों के माध्यम से लूप करता हूं और पुष्टि करता हूं कि वे मॉडल से मेल खाते हैं। मैं यह इंगित करने के लिए NoneType का उपयोग कर रहा हूं कि लौटाई गई वस्तु None भी हो सकती है - सुनिश्चित नहीं है कि यह एक अच्छा तरीका है या नहीं।

for k, v in json.items():
    assert isinstance(v, getattr(IContact, k))

मैं विशिष्ट तरीकों से संरचित तारों के साथ चाबियों के मानों को सत्यापित करने में सक्षम होना चाहता हूं, जैसे डेटाटाइम्स (आईएसओ प्रारूप), गाइड इत्यादि।

पायथन में इन डेटा संरचनाओं को मान्य करने का सबसे अच्छा तरीका क्या है? मैं पायथन 3.8.2 का उपयोग कर रहा हूं इसलिए मेरे पास सभी नवीनतम सुविधाएं हैं। मैंने संक्षेप में https://docs.python.org/3/library/dataclasses को देखा। html लेकिन मुझे यकीन नहीं है कि मुझे यही चाहिए।

0
Dillon Miller 26 मार्च 2020, 07:13

2 जवाब

मुझे लगता है कि आप JSONDecoder का उपयोग करके ढूंढ रहे हैं डिकोडिंग को अनुकूलित करने के लिए object_hook पैरामीटर। आप वहां अपना सत्यापन तर्क जोड़ सकते हैं। यह बॉक्स से बाहर सरल प्रकारों का समर्थन करता है। हो सकता है कि आपको वहां सबसे ज्यादा मिल जाए। मैं सुझाव दूंगा कि बतख अपना परिणाम टाइप करें। यदि इसमें वह डेटा है जिसकी आपको आवश्यकता है तो मान लें कि रिकॉर्ड सही है।

यदि यह महत्वपूर्ण है कि रिकॉर्ड सही प्रकार है तो डीकोड पायथन ऑब्जेक्ट को जेसन की तुलना में सत्यापित करना आसान हो सकता है।

0
Eliel Amora 26 मार्च 2020, 07:30
from dataclasses import dataclass
from typing import Optional

from validated_dc import ValidatedDC


@dataclass
class IContact(ValidatedDC):
    id: Optional[str]
    idStatus: Optional[str]
    isUser: Optional[bool]


# Let's say you got a json-string and loaded it into a dictionary
data = {
    'id': '123',
    'idStatus': 'new',
    'isUser': True
}

icontact = IContact(**data)
assert icontact.is_valid()

data = {
    'id': 123,  # <-- Error, not str and not NoneType
    'idStatus': 'new',
    'isUser': True
}

icontact = IContact(**data)

assert not icontact.is_valid()

print(icontact.get_errors())
# {'id': [BasicValidationError(value_repr='123', value_type=<class 'int'>, 
# annotation=<class 'str'>, exception=None), BasicValidationError(
# value_repr='123', value_type=<class 'int'>, annotation=<class 'NoneType'>, 
# exception=None)]}

https://github.com/EvgeniyBurdin/validated_dc

1
Evgeniy_Burdin 3 मई 2020, 18:57