code: private function parseData($data)
      {
          foreach ($data as $property_name => $property) {
              //I think the best way to handle this, will at least always be consistent
              //without writing the same code twice.
              $types_to_try = [];
              //Collect regular props
              if (isset(static::$properties[$property_name])) {
                  $types_to_try = array_merge($types_to_try, static::$properties[$property_name]);
              }
              //Collect pattern props
              foreach (static::$pattern_properties as $pattern_property) {
                  $types_to_try = array_merge($types_to_try, $pattern_property);
              }
              //Collect additional props
              if (is_array(static::$additional_properties)) {
                  $types_to_try = array_merge($types_to_try, static::$additional_properties);
              }
              if (is_array($property)) {
                  foreach ($property as $property_element) {
                      $this->add($property_name, self::tryToCast($types_to_try, $property_element));
                  }
              } else {
                  $this->set($property_name, self::tryToCast($types_to_try, $property));
              }
          }
      }
docs: Parse a schema object into the correct objects
  
  @param $data
  @throws \Exception