title: Using pydantic to deserialize sublasses of a model
body: <p>I'm using data that follows a class inheritance pattern...  I'm having trouble getting <code>pydantic</code> to deserialize it correctly for some use cases.</p>
  <p>Given the code below, it appears that the validators are not called when using the <code>parse_*</code> methods.  The type for &quot;fluffy&quot; and &quot;tiger&quot; are <code>Animal</code>, however when deserializing the &quot;bob&quot; the <code>Person</code>, his pet is the correct <code>Dog</code> type.</p>
  <p>Is there another way to approach this problem?  Using <code>pydantic</code> is not a requirement, but the ability to deserialize nested complex types (including <code>List</code> and <code>Dict</code> of objects) is.</p>
  <pre class="lang-py prettyprint-override"><code># modified from the following examples
  # - https://github.com/samuelcolvin/pydantic/issues/2177#issuecomment-739578307
  # - https://github.com/samuelcolvin/pydantic/issues/619#issuecomment-713508861
  
  from pydantic import BaseModel
  
  TIGER = &quot;&quot;&quot;{ &quot;type&quot;: &quot;cat&quot;, &quot;name&quot;: &quot;Tiger the Cat&quot;, &quot;color&quot;: &quot;tabby&quot; }&quot;&quot;&quot;
  FLUFFY = &quot;&quot;&quot;{ &quot;type&quot;: &quot;dog&quot;, &quot;name&quot;: &quot;Fluffy the Dog&quot;, &quot;color&quot;: &quot;brown&quot;, &quot;breed&quot;: &quot;rottweiler&quot; }&quot;&quot;&quot;
  
  ALICE = &quot;&quot;&quot;{ &quot;name&quot;: &quot;Alice the Person&quot; }&quot;&quot;&quot;
  BOB = f&quot;&quot;&quot;{{ &quot;name&quot;: &quot;Bob the Person&quot;, &quot;pet&quot;: {FLUFFY} }}&quot;&quot;&quot;
  
  class Animal(BaseModel):
      type: str
      name: str
      color: str = None
  
      _subtypes_ = dict()
  
      def __init_subclass__(cls, type=None):
          cls._subtypes_[type or cls.__name__.lower()] = cls
  
      @classmethod
      def __get_validators__(cls):
          yield cls._convert_to_real_type_
  
      @classmethod
      def _convert_to_real_type_(cls, data):
          data_type = data.get(&quot;type&quot;)
  
          if data_type is None:
              raise ValueError(&quot;Missing 'type' in Animal&quot;)
  
          sub = cls._subtypes_.get(data_type)
  
          if sub is None:
              raise TypeError(f&quot;Unsupport sub-type: {data_type}&quot;)
  
          return sub(**data)
  
  class Cat(Animal, type=&quot;cat&quot;):
      hairless: bool = False
  
  class Dog(Animal, type=&quot;dog&quot;):
      breed: str
  
  class Person(BaseModel):
      name: str
      pet: Animal = None
  
  tiger = Animal.parse_raw(TIGER)
  print(f&quot;tiger [{tiger.name}] =&gt; {type(tiger)} [{tiger.type}]&quot;)
  
  fluffy = Animal.parse_raw(FLUFFY)
  print(f&quot;fluffy [{fluffy.name}] =&gt; {type(fluffy)} [{fluffy.type}]&quot;)
  
  bob = Person.parse_raw(BOB)
  pet = bob.pet
  print(f&quot;bob [{bob.name}] =&gt; {type(bob)}&quot;)
  print(f&quot;pet [{pet.name}] =&gt; {type(pet)}&quot;)
  </code></pre>
  <p>Output:</p>
  <pre class="lang-sh prettyprint-override"><code>tiger [Tiger the Cat] =&gt; &lt;class '__main__.Animal'&gt;
  fluffy [Fluffy the Dog] =&gt; &lt;class '__main__.Animal'&gt;
  bob [Bob the Person] =&gt; &lt;class '__main__.Person'&gt;
  pet [Fluffy the Dog] =&gt; &lt;class '__main__.Dog'&gt;
  </code></pre>