How to get the JSON/array value property name for a field instance?
I just tested using a variety of field types, and it seems to work OK for me. Here's the code I used for testing:

$node = \Drupal\node\Entity\Node::load($nid);

print $node-&gt;get('field_test')-&gt;getFieldDefinition()-&gt;getFieldStorageDefinition()-&gt;getMainPropertyName();
print $node-&gt;get('field_test_image')-&gt;getFieldDefinition()-&gt;getFieldStorageDefinition()-&gt;getMainPropertyName();
print $node-&gt;get('field_test_link')-&gt;getFieldDefinition()-&gt;getFieldStorageDefinition()-&gt;getMainPropertyName();
print $node-&gt;get('field_test_email')-&gt;getFieldDefinition()-&gt;getFieldStorageDefinition()-&gt;getMainPropertyName();


This returns value, target_id, uri and value as one would have expected. What kind of fields are giving you trouble? How do you get you BaseFieldDefinition class? What kind of entity are they connected to?

I notice that the Views way of getting the property name is also pretty pragmatic:

// EntityField.php line 1111
if ($main_property_name = $field_item-&gt;mainPropertyName()) {
  $values[] = $field_item-&gt;{$main_property_name};
}
else {
  $values[] = $field_item-&gt;value;
}


Clearly it's not completely unexpected to have this method return null.