diff --git a/pydantic/fields.py b/pydantic/fields.py
--- a/pydantic/fields.py
+++ b/pydantic/fields.py
@@ -106,7 +106,8 @@ class FieldInfo(Representation):
         'extra',
     )
 
-    __field_constraints__ = {  # field constraints with the default value
+    # field constraints with the default value, it's also used in update_from_config below
+    __field_constraints__ = {
         'min_length': None,
         'max_length': None,
         'regex': None,
@@ -153,6 +154,20 @@ def get_constraints(self) -> Set[str]:
         """
         return {attr for attr, default in self.__field_constraints__.items() if getattr(self, attr) != default}
 
+    def update_from_config(self, from_config: Dict[str, Any]) -> None:
+        """
+        Update this FieldInfo based on a dict from get_field_info, only fields which have not been set are dated.
+        """
+        for attr_name, value in from_config.items():
+            try:
+                current_value = getattr(self, attr_name)
+            except AttributeError:
+                # attr_name is not an attribute of FieldInfo, it should therefore be added to extra
+                self.extra[attr_name] = value
+            else:
+                if current_value is self.__field_constraints__.get(attr_name, None):
+                    setattr(self, attr_name, value)
+
     def _validate(self) -> None:
         if self.default not in (Undefined, Ellipsis) and self.default_factory is not None:
             raise ValueError('cannot specify both default and default_factory')
@@ -354,17 +369,20 @@ def _get_field_info(
                 raise ValueError(f'cannot specify multiple `Annotated` `Field`s for {field_name!r}')
             field_info = next(iter(field_infos), None)
             if field_info is not None:
+                field_info.update_from_config(field_info_from_config)
                 if field_info.default not in (Undefined, Ellipsis):
                     raise ValueError(f'`Field` default cannot be set in `Annotated` for {field_name!r}')
                 if value not in (Undefined, Ellipsis):
                     field_info.default = value
+
         if isinstance(value, FieldInfo):
             if field_info is not None:
                 raise ValueError(f'cannot specify `Annotated` and value `Field`s together for {field_name!r}')
             field_info = value
-        if field_info is None:
+            field_info.update_from_config(field_info_from_config)
+        elif field_info is None:
             field_info = FieldInfo(value, **field_info_from_config)
-        field_info.alias = field_info.alias or field_info_from_config.get('alias')
+
         value = None if field_info.default_factory is not None else field_info.default
         field_info._validate()
         return field_info, value
diff --git a/pydantic/main.py b/pydantic/main.py
--- a/pydantic/main.py
+++ b/pydantic/main.py
@@ -142,6 +142,10 @@ class BaseConfig:
 
     @classmethod
     def get_field_info(cls, name: str) -> Dict[str, Any]:
+        """
+        Get properties of FieldInfo from the `fields` property of the config class.
+        """
+
         fields_value = cls.fields.get(name)
 
         if isinstance(fields_value, str):

Thanks for reporting, see the discussion on #2437, this is rooted in a wider problem which I'm fixing now.
diff --git a/tests/test_annotated.py b/tests/test_annotated.py
--- a/tests/test_annotated.py
+++ b/tests/test_annotated.py
@@ -2,12 +2,10 @@
 from typing import get_type_hints
 
 import pytest
+from typing_extensions import Annotated
 
 from pydantic import BaseModel, Field
 from pydantic.fields import Undefined
-from pydantic.typing import Annotated
-
-pytestmark = pytest.mark.skipif(not Annotated, reason='typing_extensions not installed')
 
 
 @pytest.mark.parametrize(
@@ -26,12 +24,12 @@
         ),
         # Test valid Annotated Field uses
         pytest.param(
-            lambda: Annotated[int, Field(description='Test')],
+            lambda: Annotated[int, Field(description='Test')],  # noqa: F821
             5,
             id='annotated-field-value-default',
         ),
         pytest.param(
-            lambda: Annotated[int, Field(default_factory=lambda: 5, description='Test')],
+            lambda: Annotated[int, Field(default_factory=lambda: 5, description='Test')],  # noqa: F821
             Undefined,
             id='annotated-field-default_factory',
         ),
@@ -132,3 +130,15 @@ class AnnotatedModel(BaseModel):
         one: Annotated[int, field]
 
     assert AnnotatedModel(one=1).dict() == {'one': 1}
+
+
+def test_config_field_info():
+    class Foo(BaseModel):
+        a: Annotated[int, Field(foobar='hello')]  # noqa: F821
+
+        class Config:
+            fields = {'a': {'description': 'descr'}}
+
+    assert Foo.schema(by_alias=True)['properties'] == {
+        'a': {'title': 'A', 'description': 'descr', 'foobar': 'hello', 'type': 'integer'},
+    }
diff --git a/tests/test_create_model.py b/tests/test_create_model.py
--- a/tests/test_create_model.py
+++ b/tests/test_create_model.py
@@ -1,6 +1,6 @@
 import pytest
 
-from pydantic import BaseModel, Extra, ValidationError, create_model, errors, validator
+from pydantic import BaseModel, Extra, Field, ValidationError, create_model, errors, validator
 
 
 def test_create_model():
@@ -194,3 +194,14 @@ class A(BaseModel):
 
     for field_name in ('x', 'y', 'z'):
         assert A.__fields__[field_name].default == DynamicA.__fields__[field_name].default
+
+
+def test_config_field_info_create_model():
+    class Config:
+        fields = {'a': {'description': 'descr'}}
+
+    m1 = create_model('M1', __config__=Config, a=(str, ...))
+    assert m1.schema()['properties'] == {'a': {'title': 'A', 'description': 'descr', 'type': 'string'}}
+
+    m2 = create_model('M2', __config__=Config, a=(str, Field(...)))
+    assert m2.schema()['properties'] == {'a': {'title': 'A', 'description': 'descr', 'type': 'string'}}
diff --git a/tests/test_dataclasses.py b/tests/test_dataclasses.py
--- a/tests/test_dataclasses.py
+++ b/tests/test_dataclasses.py
@@ -901,3 +901,22 @@ class Config:
     # ensure the restored dataclass is still a pydantic dataclass
     with pytest.raises(ValidationError, match='value\n +value is not a valid integer'):
         restored_obj.dataclass.value = 'value of a wrong type'
+
+
+def test_config_field_info_create_model():
+    # works
+    class A1(BaseModel):
+        a: str
+
+        class Config:
+            fields = {'a': {'description': 'descr'}}
+
+    assert A1.schema()['properties'] == {'a': {'title': 'A', 'description': 'descr', 'type': 'string'}}
+
+    @pydantic.dataclasses.dataclass(config=A1.Config)
+    class A2:
+        a: str
+
+    assert A2.__pydantic_model__.schema()['properties'] == {
+        'a': {'title': 'A', 'description': 'descr', 'type': 'string'}
+    }
diff --git a/tests/test_edge_cases.py b/tests/test_edge_cases.py
--- a/tests/test_edge_cases.py
+++ b/tests/test_edge_cases.py
@@ -1779,3 +1779,63 @@ class MyModel(BaseModel):
         y: str = 'a'
 
     assert list(MyModel()._iter(by_alias=True)) == [('x', 1), ('y', 'a')]
+
+
+def test_config_field_info():
+    class Foo(BaseModel):
+        a: str = Field(...)
+
+        class Config:
+            fields = {'a': {'description': 'descr'}}
+
+    assert Foo.schema(by_alias=True)['properties'] == {'a': {'title': 'A', 'description': 'descr', 'type': 'string'}}
+
+
+def test_config_field_info_alias():
+    class Foo(BaseModel):
+        a: str = Field(...)
+
+        class Config:
+            fields = {'a': {'alias': 'b'}}
+
+    assert Foo.schema(by_alias=True)['properties'] == {'b': {'title': 'B', 'type': 'string'}}
+
+
+def test_config_field_info_merge():
+    class Foo(BaseModel):
+        a: str = Field(..., foo='Foo')
+
+        class Config:
+            fields = {'a': {'bar': 'Bar'}}
+
+    assert Foo.schema(by_alias=True)['properties'] == {
+        'a': {'bar': 'Bar', 'foo': 'Foo', 'title': 'A', 'type': 'string'}
+    }
+
+
+def test_config_field_info_allow_mutation():
+    class Foo(BaseModel):
+        a: str = Field(...)
+
+        class Config:
+            validate_assignment = True
+
+    assert Foo.__fields__['a'].field_info.allow_mutation is True
+
+    f = Foo(a='x')
+    f.a = 'y'
+    assert f.dict() == {'a': 'y'}
+
+    class Bar(BaseModel):
+        a: str = Field(...)
+
+        class Config:
+            fields = {'a': {'allow_mutation': False}}
+            validate_assignment = True
+
+    assert Bar.__fields__['a'].field_info.allow_mutation is False
+
+    b = Bar(a='x')
+    with pytest.raises(TypeError):
+        b.a = 'y'
+    assert b.dict() == {'a': 'x'}

dataclass config fields not warranted in json schema (1.8)
### Checks

* [X] I added a descriptive title to this issue
* [X] I have searched (google, github) for similar issues and couldn't find anything
* [X] I have read and followed [the docs](https://pydantic-docs.helpmanual.io/) and still think this is a bug

# Bug

Output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())"`:
```
             pydantic version: 1.8
            pydantic compiled: True
                 install path: /Users/dafcok/miniconda3/lib/python3.6/site-packages/pydantic
               python version: 3.6.8 |Anaconda, Inc.| (default, Dec 29 2018, 19:04:46)  [GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]
                     platform: Darwin-19.6.0-x86_64-i386-64bit
     optional deps. installed: ['devtools', 'dotenv', 'email-validator', 'typing-extensions'
```
```py
from pydantic import BaseModel
from pydantic.dataclasses import dataclass

# works
class A(BaseModel):
    a: str

    class Config:
        fields = {"a": {"description": "descr"}}

assert A.schema()["properties"]["a"]["description"] == "descr"

# works on 1.7.3
# fails on 1.8
@dataclass(config=A.Config)
class Ad:
    a: str

assert Ad.__pydantic_model__.schema()["properties"]["a"]["description"] == "descr"
```
```bash
Traceback (most recent call last):
  File "tests/test_schema_descr.py", line 24, in <module>
    assert Ad.__pydantic_model__.schema()["properties"]["a"]["description"] == "descr"
KeyError: 'description
```
It seems that `config.fields` is not processed in the decorator.

tests/test_annotated.py::test_config_field_info tests/test_create_model.py::test_config_field_info_create_model tests/test_dataclasses.py::test_config_field_info_create_model tests/test_edge_cases.py::test_config_field_info tests/test_edge_cases.py::test_config_field_info_merge tests/test_edge_cases.py::test_config_field_info_allow_mutation
tests/test_annotated.py::test_annotated[misc-default] tests/test_annotated.py::test_annotated[misc-field-default-constraint] tests/test_annotated.py::test_annotated[annotated-field-value-default] tests/test_annotated.py::test_annotated[annotated-field-default_factory] tests/test_annotated.py::test_annotated_model_exceptions[annotated-field-default] tests/test_annotated.py::test_annotated_model_exceptions[annotated-field-dup] tests/test_annotated.py::test_annotated_model_exceptions[annotated-field-value-field-dup] tests/test_annotated.py::test_annotated_model_exceptions[annotated-field-default_factory-value-default] tests/test_annotated.py::test_annotated_instance_exceptions[misc-no-default] tests/test_annotated.py::test_annotated_instance_exceptions[annotated-field-no-default] tests/test_annotated.py::test_field_reuse tests/test_create_model.py::test_create_model tests/test_create_model.py::test_create_model_usage tests/test_create_model.py::test_create_model_pickle tests/test_create_model.py::test_invalid_name tests/test_create_model.py::test_field_wrong_tuple tests/test_create_model.py::test_config_and_base tests/test_create_model.py::test_inheritance tests/test_create_model.py::test_custom_config tests/test_create_model.py::test_custom_config_inherits tests/test_create_model.py::test_custom_config_extras tests/test_create_model.py::test_inheritance_validators tests/test_create_model.py::test_inheritance_validators_always tests/test_create_model.py::test_inheritance_validators_all tests/test_create_model.py::test_funky_name tests/test_create_model.py::test_repeat_base_usage tests/test_create_model.py::test_dynamic_and_static tests/test_dataclasses.py::test_simple tests/test_dataclasses.py::test_model_name tests/test_dataclasses.py::test_value_error tests/test_dataclasses.py::test_frozen tests/test_dataclasses.py::test_validate_assignment tests/test_dataclasses.py::test_validate_assignment_error tests/test_dataclasses.py::test_not_validate_assignment tests/test_dataclasses.py::test_validate_assignment_value_change tests/test_dataclasses.py::test_validate_assignment_extra tests/test_dataclasses.py::test_post_init tests/test_dataclasses.py::test_post_init_inheritance_chain tests/test_dataclasses.py::test_post_init_post_parse tests/test_dataclasses.py::test_post_init_post_parse_types tests/test_dataclasses.py::test_post_init_assignment tests/test_dataclasses.py::test_inheritance tests/test_dataclasses.py::test_validate_long_string_error tests/test_dataclasses.py::test_validate_assigment_long_string_error tests/test_dataclasses.py::test_no_validate_assigment_long_string_error tests/test_dataclasses.py::test_nested_dataclass tests/test_dataclasses.py::test_arbitrary_types_allowed tests/test_dataclasses.py::test_nested_dataclass_model tests/test_dataclasses.py::test_fields tests/test_dataclasses.py::test_default_factory_field tests/test_dataclasses.py::test_default_factory_singleton_field tests/test_dataclasses.py::test_schema tests/test_dataclasses.py::test_nested_schema tests/test_dataclasses.py::test_initvar tests/test_dataclasses.py::test_derived_field_from_initvar tests/test_dataclasses.py::test_initvars_post_init tests/test_dataclasses.py::test_initvars_post_init_post_parse tests/test_dataclasses.py::test_classvar tests/test_dataclasses.py::test_frozenset_field tests/test_dataclasses.py::test_inheritance_post_init tests/test_dataclasses.py::test_hashable_required tests/test_dataclasses.py::test_hashable_optional[1] tests/test_dataclasses.py::test_hashable_optional[None] tests/test_dataclasses.py::test_hashable_optional[default2] tests/test_dataclasses.py::test_override_builtin_dataclass tests/test_dataclasses.py::test_override_builtin_dataclass_2 tests/test_dataclasses.py::test_override_builtin_dataclass_nested tests/test_dataclasses.py::test_override_builtin_dataclass_nested_schema tests/test_dataclasses.py::test_inherit_builtin_dataclass tests/test_dataclasses.py::test_dataclass_arbitrary tests/test_dataclasses.py::test_forward_stdlib_dataclass_params tests/test_dataclasses.py::test_pydantic_callable_field tests/test_dataclasses.py::test_pickle_overriden_builtin_dataclass tests/test_edge_cases.py::test_str_bytes tests/test_edge_cases.py::test_str_bytes_none tests/test_edge_cases.py::test_union_int_str tests/test_edge_cases.py::test_union_priority tests/test_edge_cases.py::test_typed_list tests/test_edge_cases.py::test_typed_set tests/test_edge_cases.py::test_dict_dict tests/test_edge_cases.py::test_none_list tests/test_edge_cases.py::test_typed_dict[value0-result0] tests/test_edge_cases.py::test_typed_dict[value1-result1] tests/test_edge_cases.py::test_typed_dict[value2-result2] tests/test_edge_cases.py::test_typed_dict_error[1-errors0] tests/test_edge_cases.py::test_typed_dict_error[value1-errors1] tests/test_edge_cases.py::test_typed_dict_error[value2-errors2] tests/test_edge_cases.py::test_dict_key_error tests/test_edge_cases.py::test_tuple tests/test_edge_cases.py::test_tuple_more tests/test_edge_cases.py::test_tuple_length_error tests/test_edge_cases.py::test_tuple_invalid tests/test_edge_cases.py::test_tuple_value_error tests/test_edge_cases.py::test_recursive_list tests/test_edge_cases.py::test_recursive_list_error tests/test_edge_cases.py::test_list_unions tests/test_edge_cases.py::test_recursive_lists tests/test_edge_cases.py::test_str_enum tests/test_edge_cases.py::test_any_dict tests/test_edge_cases.py::test_success_values_include tests/test_edge_cases.py::test_include_exclude_unset tests/test_edge_cases.py::test_include_exclude_defaults tests/test_edge_cases.py::test_skip_defaults_deprecated tests/test_edge_cases.py::test_advanced_exclude tests/test_edge_cases.py::test_advanced_exclude_by_alias tests/test_edge_cases.py::test_advanced_value_include tests/test_edge_cases.py::test_advanced_value_exclude_include tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude0-expected0] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude1-expected1] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude2-expected2] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude3-expected3] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude4-expected4] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude5-expected5] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude6-expected6] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude7-expected7] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude8-expected8] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude9-expected9] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude10-expected10] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude11-expected11] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude12-expected12] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude13-expected13] tests/test_edge_cases.py::test_advanced_exclude_nested_lists[exclude14-expected14] tests/test_edge_cases.py::test_advanced_include_nested_lists[include0-expected0] tests/test_edge_cases.py::test_advanced_include_nested_lists[include1-expected1] tests/test_edge_cases.py::test_advanced_include_nested_lists[include2-expected2] tests/test_edge_cases.py::test_advanced_include_nested_lists[include3-expected3] tests/test_edge_cases.py::test_advanced_include_nested_lists[include4-expected4] tests/test_edge_cases.py::test_advanced_include_nested_lists[include5-expected5] tests/test_edge_cases.py::test_advanced_include_nested_lists[include6-expected6] tests/test_edge_cases.py::test_advanced_include_nested_lists[include7-expected7] tests/test_edge_cases.py::test_advanced_include_nested_lists[include8-expected8] tests/test_edge_cases.py::test_advanced_include_nested_lists[include9-expected9] tests/test_edge_cases.py::test_advanced_include_nested_lists[include10-expected10] tests/test_edge_cases.py::test_advanced_include_nested_lists[include11-expected11] tests/test_edge_cases.py::test_advanced_include_nested_lists[include12-expected12] tests/test_edge_cases.py::test_advanced_include_nested_lists[include13-expected13] tests/test_edge_cases.py::test_advanced_include_nested_lists[include14-expected14] tests/test_edge_cases.py::test_field_set_ignore_extra tests/test_edge_cases.py::test_field_set_allow_extra tests/test_edge_cases.py::test_field_set_field_name tests/test_edge_cases.py::test_values_order tests/test_edge_cases.py::test_inheritance tests/test_edge_cases.py::test_invalid_type tests/test_edge_cases.py::test_valid_string_types[a tests/test_edge_cases.py::test_valid_string_types[some tests/test_edge_cases.py::test_valid_string_types[value2-foobar] tests/test_edge_cases.py::test_valid_string_types[123-123] tests/test_edge_cases.py::test_valid_string_types[123.45-123.45] tests/test_edge_cases.py::test_valid_string_types[value5-12.45] tests/test_edge_cases.py::test_valid_string_types[True-True] tests/test_edge_cases.py::test_valid_string_types[False-False] tests/test_edge_cases.py::test_valid_string_types[a10-a10] tests/test_edge_cases.py::test_valid_string_types[whatever-whatever] tests/test_edge_cases.py::test_invalid_string_types[value0-errors0] tests/test_edge_cases.py::test_invalid_string_types[value1-errors1] tests/test_edge_cases.py::test_inheritance_config tests/test_edge_cases.py::test_partial_inheritance_config tests/test_edge_cases.py::test_annotation_inheritance tests/test_edge_cases.py::test_string_none tests/test_edge_cases.py::test_return_errors_ok tests/test_edge_cases.py::test_return_errors_error tests/test_edge_cases.py::test_optional_required tests/test_edge_cases.py::test_invalid_validator tests/test_edge_cases.py::test_unable_to_infer tests/test_edge_cases.py::test_multiple_errors tests/test_edge_cases.py::test_validate_all tests/test_edge_cases.py::test_force_extra tests/test_edge_cases.py::test_illegal_extra_value tests/test_edge_cases.py::test_multiple_inheritance_config tests/test_edge_cases.py::test_submodel_different_type tests/test_edge_cases.py::test_self tests/test_edge_cases.py::test_self_recursive[BaseModel] tests/test_edge_cases.py::test_self_recursive[BaseSettings] tests/test_edge_cases.py::test_nested_init[BaseModel] tests/test_edge_cases.py::test_nested_init[BaseSettings] tests/test_edge_cases.py::test_init_inspection tests/test_edge_cases.py::test_type_on_annotation tests/test_edge_cases.py::test_assign_type tests/test_edge_cases.py::test_optional_subfields tests/test_edge_cases.py::test_not_optional_subfields tests/test_edge_cases.py::test_optional_field_constraints tests/test_edge_cases.py::test_field_str_shape tests/test_edge_cases.py::test_field_type_display[int-int] tests/test_edge_cases.py::test_field_type_display[type_1-Optional[int]] tests/test_edge_cases.py::test_field_type_display[type_2-Union[NoneType, tests/test_edge_cases.py::test_field_type_display[type_3-Union[int, tests/test_edge_cases.py::test_field_type_display[type_4-List[int]] tests/test_edge_cases.py::test_field_type_display[type_5-Tuple[int, tests/test_edge_cases.py::test_field_type_display[type_6-Union[List[int], tests/test_edge_cases.py::test_field_type_display[type_7-List[Tuple[int, tests/test_edge_cases.py::test_field_type_display[type_8-Mapping[int, tests/test_edge_cases.py::test_field_type_display[type_9-FrozenSet[int]] tests/test_edge_cases.py::test_field_type_display[type_10-Tuple[int, tests/test_edge_cases.py::test_field_type_display[type_11-Optional[List[int]]] tests/test_edge_cases.py::test_field_type_display[dict-dict] tests/test_edge_cases.py::test_field_type_display[type_13-DisplayGen[bool, tests/test_edge_cases.py::test_any_none tests/test_edge_cases.py::test_type_var_any tests/test_edge_cases.py::test_type_var_constraint tests/test_edge_cases.py::test_type_var_bound tests/test_edge_cases.py::test_dict_bare tests/test_edge_cases.py::test_list_bare tests/test_edge_cases.py::test_dict_any tests/test_edge_cases.py::test_modify_fields tests/test_edge_cases.py::test_exclude_none tests/test_edge_cases.py::test_exclude_none_recursive tests/test_edge_cases.py::test_exclude_none_with_extra tests/test_edge_cases.py::test_str_method_inheritance tests/test_edge_cases.py::test_repr_method_inheritance tests/test_edge_cases.py::test_optional_validator tests/test_edge_cases.py::test_required_optional tests/test_edge_cases.py::test_required_any tests/test_edge_cases.py::test_custom_generic_validators tests/test_edge_cases.py::test_custom_generic_arbitrary_allowed tests/test_edge_cases.py::test_custom_generic_disallowed tests/test_edge_cases.py::test_hashable_required tests/test_edge_cases.py::test_hashable_optional[1] tests/test_edge_cases.py::test_hashable_optional[None] tests/test_edge_cases.py::test_default_factory_side_effect tests/test_edge_cases.py::test_default_factory_validator_child tests/test_edge_cases.py::test_cython_function_untouched tests/test_edge_cases.py::test_resolve_annotations_module_missing tests/test_edge_cases.py::test_iter_coverage tests/test_edge_cases.py::test_config_field_info_alias