diff --git a/common/database/database_lib_settings.cpp b/common/database/database_lib_settings.cpp
index 4b1e091258..af579ef6fe 100644
--- a/common/database/database_lib_settings.cpp
+++ b/common/database/database_lib_settings.cpp
@@ -78,29 +78,18 @@ DATABASE_LIB_SETTINGS::DATABASE_LIB_SETTINGS( const std::string& aFilename ) :
                 {
                     const nlohmann::json& pj = entry["properties"];
 
-                    if( pj.contains( "description" ) )
-                        table.properties.description = pj["description"].get<std::string>();
+                    table.properties.description = fetchOrDefault<std::string>( pj, "description" );
 
-                    if( pj.contains( "footprint_filters" ) )
-                    {
-                        table.properties.footprint_filters =
-                                pj["footprint_filters"].get<std::string>();
-                    }
+                    table.properties.footprint_filters =
+                            fetchOrDefault<std::string>( pj, "footprint_filters" );
 
-                    if( pj.contains( "keywords" ) )
-                        table.properties.keywords = pj["keywords"].get<std::string>();
+                    table.properties.keywords = fetchOrDefault<std::string>( pj, "keywords" );
 
-                    if( pj.contains( "exclude_from_bom" ) )
-                    {
-                        table.properties.exclude_from_bom =
-                                pj["exclude_from_bom"].get<std::string>();
-                    }
+                    table.properties.exclude_from_bom =
+                            fetchOrDefault<std::string>( pj, "exclude_from_bom" );
 
-                    if( pj.contains( "exclude_from_board" ) )
-                    {
-                        table.properties.exclude_from_board =
-                                pj["exclude_from_board"].get<std::string>();
-                    }
+                    table.properties.exclude_from_board =
+                            fetchOrDefault<std::string>( pj, "exclude_from_board" );
                 }
 
                 if( entry.contains( "fields" ) && entry["fields"].is_array() )
@@ -110,26 +99,19 @@ DATABASE_LIB_SETTINGS::DATABASE_LIB_SETTINGS( const std::string& aFilename ) :
                         if( fieldJson.empty() || !fieldJson.is_object() )
                             continue;
 
-                        std::string column = fieldJson.contains( "column" )
-                                             ? fieldJson["column"].get<std::string>() : "";
-
-                        std::string name   = fieldJson.contains( "name" )
-                                             ? fieldJson["name"].get<std::string>() : "";
-
-                        bool visible_on_add = !fieldJson.contains( "visible_on_add" )
-                                              || fieldJson["visible_on_add"].get<bool>();
-
+                        std::string column  = fetchOrDefault<std::string>( fieldJson, "column" );
+                        std::string name    = fetchOrDefault<std::string>( fieldJson, "name" );
+                        bool visible_on_add = fetchOrDefault<bool>( fieldJson, "visible_on_add" );
                         bool visible_in_chooser =
-                                !fieldJson.contains( "visible_in_chooser" )
-                                || fieldJson["visible_in_chooser"].get<bool>();
-
-                        bool show_name = fieldJson.contains( "show_name" )
-                                         && fieldJson["show_name"].get<bool>();
+                                fetchOrDefault<bool>( fieldJson, "visible_in_chooser" );
+                        bool show_name = fetchOrDefault<bool>( fieldJson, "show_name" );
+                        bool inherit   = fetchOrDefault<bool>( fieldJson, "inherit_properties" );
 
                         table.fields.emplace_back(
                                 DATABASE_FIELD_MAPPING(
                                 {
-                                    column, name, visible_on_add, visible_in_chooser, show_name
+                                    column, name, visible_on_add, visible_in_chooser, show_name,
+                                    inherit
                                 } ) );
                     }
                 }
diff --git a/common/settings/json_settings.cpp b/common/settings/json_settings.cpp
index 761c623183..6a4c01d083 100644
--- a/common/settings/json_settings.cpp
+++ b/common/settings/json_settings.cpp
@@ -836,3 +836,29 @@ void from_json( const nlohmann::json& aJson, wxString& aString )
 {
     aString = wxString( aJson.get<std::string>().c_str(), wxConvUTF8 );
 }
+
+
+template<typename ResultType>
+ResultType JSON_SETTINGS::fetchOrDefault( const nlohmann::json& aJson, const std::string& aKey,
+                                          ResultType aDefault )
+{
+    ResultType ret = aDefault;
+
+    try
+    {
+        if( aJson.contains( aKey ) )
+            ret = aJson.at( aKey ).get<ResultType>();
+    }
+    catch( ... )
+    {
+    }
+
+    return ret;
+}
+
+
+template std::string JSON_SETTINGS::fetchOrDefault( const nlohmann::json& aJson,
+                                                    const std::string& aKey, std::string aDefault );
+
+template bool JSON_SETTINGS::fetchOrDefault( const nlohmann::json& aJson, const std::string& aKey,
+                                             bool aDefault );
diff --git a/eeschema/sch_plugins/database/sch_database_plugin.cpp b/eeschema/sch_plugins/database/sch_database_plugin.cpp
index 4a25172b34..8b4b703041 100644
--- a/eeschema/sch_plugins/database/sch_database_plugin.cpp
+++ b/eeschema/sch_plugins/database/sch_database_plugin.cpp
@@ -19,6 +19,7 @@
  */
 
 #include <iostream>
+#include <unordered_set>
 
 #include <boost/algorithm/string.hpp>
 
@@ -349,6 +350,14 @@ LIB_SYMBOL* SCH_DATABASE_PLUGIN::loadSymbolFromRow( const wxString& aSymbolName,
         symbol->SetIncludeInBom( !exclude );
     }
 
+    std::vector<LIB_FIELD*> fields;
+    symbol->GetFields( fields );
+
+    std::unordered_map<wxString, LIB_FIELD*> fieldsMap;
+
+    for( LIB_FIELD* field : fields )
+        fieldsMap[field->GetName()] = field;
+
     for( const DATABASE_FIELD_MAPPING& mapping : aTable.fields )
     {
         if( !aRow.count( mapping.column ) )
@@ -382,14 +391,32 @@ LIB_SYMBOL* SCH_DATABASE_PLUGIN::loadSymbolFromRow( const wxString& aSymbolName,
             continue;
         }
 
-        LIB_FIELD* field = new LIB_FIELD( symbol->GetNextAvailableFieldId() );
-        field->SetName( mapping.name );
-        field->SetText( value );
-        field->SetVisible( mapping.visible_on_add );
-        field->SetAutoAdded( true );
-        field->SetNameShown( mapping.show_name );
+        LIB_FIELD* field;
+        bool isNew = false;
 
-        symbol->AddField( field );
+        if( fieldsMap.count( mapping.name ) )
+        {
+            field = fieldsMap[mapping.name];
+        }
+        else
+        {
+            field = new LIB_FIELD( symbol->GetNextAvailableFieldId() );
+            field->SetName( mapping.name );
+            isNew = true;
+            fieldsMap[mapping.name] = field;
+        }
+
+        if( !mapping.inherit_properties || isNew )
+        {
+            field->SetVisible( mapping.visible_on_add );
+            field->SetAutoAdded( true );
+            field->SetNameShown( mapping.show_name );
+        }
+
+        field->SetText( value );
+
+        if( isNew )
+            symbol->AddField( field );
 
         m_customFields.insert( mapping.name );
 
diff --git a/include/database/database_lib_settings.h b/include/database/database_lib_settings.h
index 60b42ff059..520bd72290 100644
--- a/include/database/database_lib_settings.h
+++ b/include/database/database_lib_settings.h
@@ -49,6 +49,7 @@ struct DATABASE_FIELD_MAPPING
     bool        visible_on_add;      ///< Whether to show the field when placing the symbol
     bool        visible_in_chooser;  ///< Whether the column is shown by default in the chooser
     bool        show_name;           ///< Whether or not to show the field name as well as its value
+    bool        inherit_properties;  ///< Whether or not to inherit properties from symbol field
 };
 
 
diff --git a/include/settings/json_settings.h b/include/settings/json_settings.h
index 0241c182ae..d8890a550f 100644
--- a/include/settings/json_settings.h
+++ b/include/settings/json_settings.h
@@ -282,6 +282,17 @@ protected:
         return wxEmptyString;
     }
 
+    /**
+     * Helper to retrieve a value from a JSON object (dictionary) as a certain result type
+     * @tparam ResultType is the type of the retrieved value.
+     * @param aJson is the object to act on .
+     * @param aKey is the object key to retrieve the value for.
+     * @return the result, or aDefault if aKey is not found.
+     */
+    template<typename ResultType>
+    static ResultType fetchOrDefault( const nlohmann::json& aJson, const std::string& aKey,
+                                      ResultType aDefault = ResultType() );
+
     /// The filename (not including path) of this settings file (inicode)
     wxString m_filename;