Repository: pydantic/pydantic

Issue:
Add "camelCase" mode
Hello guys, 
At my company, our apis uses camelCase for all dictionnaire keys in json request and response bodies. That's a company guideline that came from the fact we communicate with several API's written in diverse languages. Since camelCase is the way variables are written in JS, we chose that.


This awesome library is quite useful for us. I'm using it, but before every *request* and every *response* I have to transform my dict.

Maybe you should support a ***camelCase mode*** just like [Serde](https://serde.rs/) does 





Discussion:
I'm not clear how pydantic needs to change. Can't you just set the attribute/field names to be camel case?
I like PEP8, If I rename properties names I can't follow it.

Besides my own classes, the json errors returned by pydantic are written snake_case. 

I would appreciated a "camelCase" mode for the same reason serde.rs support it:  because of naming conventions are important. And  *transform every key* is boring and inneficient.


Humm, you can already have alternative names using config fields. But it would be possible to add such a setting or allow you to easily override the base model. I'll look into it. 

Resolving patch:
diff --git a/pydantic/fields.py b/pydantic/fields.py
--- a/pydantic/fields.py
+++ b/pydantic/fields.py
@@ -72,7 +72,7 @@ def __init__(
     @classmethod
     def infer(cls, *, name, value, annotation, class_validators, config):
         required = value == Required
-        field_config = _get_field_config(config, name)
+        field_config = config.get_field_config(name)
         return cls(
             name=name,
             type_=annotation,
@@ -86,7 +86,7 @@ def infer(cls, *, name, value, annotation, class_validators, config):
 
     def set_config(self, config):
         self.model_config = config
-        field_config = _get_field_config(config, self.name)
+        field_config = config.get_field_config(self.name)
         if field_config:
             self.alias = field_config.get('alias') or self.alias
             self.description = field_config.get('description') or self.description
@@ -345,13 +345,6 @@ def _get_validator_signature(validator):
                           f'(cls, value) or (cls, value, *, values, config, field)') from e
 
 
-def _get_field_config(config, name):
-    field_config = config.fields.get(name)
-    if isinstance(field_config, str):
-        field_config = {'alias': field_config}
-    return field_config
-
-
 def _get_type_origin(obj):
     """
     Like obj.__class__ or type(obj) but for typing objects
diff --git a/pydantic/main.py b/pydantic/main.py
--- a/pydantic/main.py
+++ b/pydantic/main.py
@@ -28,14 +28,22 @@ class BaseConfig:
     fields = {}
     validate_assignment = False
 
+    @classmethod
+    def get_field_config(cls, name):
+        field_config = cls.fields.get(name) or {}
+        if isinstance(field_config, str):
+            field_config = {'alias': field_config}
+        return field_config
+
 
-def inherit_config(self_config, parent_config) -> Type[BaseConfig]:
+def inherit_config(self_config: Type[BaseConfig], parent_config: Type[BaseConfig]) -> Type[BaseConfig]:
     if not self_config:
-        return parent_config
-    for k, v in parent_config.__dict__.items():
-        if not (k.startswith('_') or hasattr(self_config, k)):
-            setattr(self_config, k, v)
-    return self_config
+        base_classes = parent_config,
+    elif self_config == parent_config:
+        base_classes = self_config,
+    else:
+        base_classes = self_config, parent_config
+    return type('Config', base_classes, {})
 
 
 TYPE_BLACKLIST = FunctionType, property, type, classmethod, staticmethod


Test patch:
diff --git a/tests/test_complex.py b/tests/test_complex.py
--- a/tests/test_complex.py
+++ b/tests/test_complex.py
@@ -1,10 +1,11 @@
+import re
 from decimal import Decimal
 from enum import Enum
 from typing import Any, Dict, List, Set, Union
 
 import pytest
 
-from pydantic import BaseModel, NoneStrBytes, StrBytes, ValidationError, constr
+from pydantic import BaseConfig, BaseModel, NoneStrBytes, StrBytes, ValidationError, constr
 from pydantic.exceptions import pretty_errors
 
 
@@ -539,3 +540,46 @@ def test_dict_list_error():
             'error_msg': 'value is not a valid dict, got list',
         }
     } == dict(exc_info.value.errors_dict)
+
+
+def test_alias_camel_case():
+    class Model(BaseModel):
+        one_thing: int
+        another_thing: int
+
+        class Config(BaseConfig):
+            @classmethod
+            def get_field_config(cls, name):
+                field_config = super().get_field_config(name) or {}
+                if 'alias' not in field_config:
+                    field_config['alias'] = re.sub(r'(?:^|_)([a-z])', lambda m: m.group(1).upper(), name)
+                return field_config
+
+    v = Model(**{'OneThing': 123, 'AnotherThing': '321'})
+    assert v.one_thing == 123
+    assert v.another_thing == 321
+    assert v == {'one_thing': 123, 'another_thing': 321}
+
+
+def test_get_field_config_inherit():
+    class ModelOne(BaseModel):
+        class Config(BaseConfig):
+            @classmethod
+            def get_field_config(cls, name):
+                field_config = super().get_field_config(name) or {}
+                if 'alias' not in field_config:
+                    field_config['alias'] = re.sub(r'_([a-z])', lambda m: m.group(1).upper(), name)
+                return field_config
+
+    class ModelTwo(ModelOne):
+        one_thing: int
+        another_thing: int
+        third_thing: int
+
+        class Config:
+            fields = {
+                'third_thing': 'Banana'
+            }
+
+    v = ModelTwo(**{'oneThing': 123, 'anotherThing': '321', 'Banana': 1})
+    assert v == {'one_thing': 123, 'another_thing': 321, 'third_thing': 1}
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
@@ -10,7 +10,7 @@ def test_create_model():
     assert model.__name__ == 'FooModel'
     assert model.__fields__.keys() == {'foo', 'bar'}
     assert model.__validators__ == {}
-    assert model.__config__.__name__ == 'BaseConfig'
+    assert model.__config__.__name__ == 'Config'
 
 
 def test_create_model_usage():