title: Validate structure of str returned from data via data model
body: <p>I'm trying to find the best way to validate the integrity of data I receive back from an api. </p>
  
  <p>For example, I have a data set that matches a model (IContact).</p>
  
  <p><strong>Data:</strong></p>
  
  <pre><code>{
      '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
  }
  </code></pre>
  
  <p><strong>Model:</strong></p>
  
  <pre><code>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)
  </code></pre>
  
  <p>In my tests I loop through the keys I receive from the api (json) and confirm they match with the model. I'm using <code>NoneType</code> to indicate that the object returned can be <code>None</code> as well - not sure if this is a good approach.</p>
  
  <pre><code>for k, v in json.items():
      assert isinstance(v, getattr(IContact, k))
  </code></pre>
  
  <p>I'd like to be able to validate the values for keys with strings structured in specific ways, like datetimes (iso format), guids, etc.</p>
  
  <p><strong>What is the best approach to validate these data structures in Python?</strong> I'm using Python 3.8.2 so I have all the latest features. I briefly looked at <a href="https://docs.python.org/3/library/dataclasses.html" rel="nofollow noreferrer">https://docs.python.org/3/library/dataclasses.html</a> but I'm not sure if that is what I need.</p>