$def

It allows you to define a reusable subschema

{  
	"$defs": {  
		"stringType": {  
			"type": "string"  
		}  
	}  
}  

$ref

It allows you to reference a reusable subschema.

{  
	"$defs": {  
		"stringType": {  
			"type": "string"  
		}  
	},  
	"type": "object",   
	"properties": {  
		"firstName": {  
			"$ref": "#/$defs/stringType"  
		}  
	}  
}  

If you want to reference a schema, you have to use $ref as a key and then the path to the definition of your schema. If you want to self reference the schema, use # to go to the root of the schema and then traverse to the subschema definition in your $defs.

$id

$id is useful when you want to add a URI to your schema that people can use to access it. It is extremely useful when you want to publish your schemas so they are accessible in many other codebases.

{  
	"$id": "https://example.com/person",  
	"type": "object",  
	"properties": {  
		"name": {  
			"type": "string"  
		}  
	}  
}  

To be able to access schema, you have to use ref and provide a URL to it.

{  
	"$ref": "https://example.com/person"  
}