Cambiar nombres de campos de un Serializer (DRF) en runtime

Buenas!

Estoy usando Django Rest Framework.

Consumo una API que devuelve los campos en mayúsculas. Ejemplo:

{
  "CODIGO": 1,
  "NOMBREPERSONA": "Marco",
  "APELLIDOPERSONA": "Richetta"
}

Creé un serializer para recibir y validar esos datos.

class EmpleadoSerializer(serializers.Serializer):

    CODIGO = serializers.IntegerField()
    NOMBREPERSONA = serializers.CharField()
    APELLIDOPERSONA = serializers.CharField()

Problema

Lo que necesito es cambiar los nombres de los campos a camelCase pero no estoy seguro cuál es el mejor lugar para hacerlo.

De momento sobrescribí el método to_representation del serializer de la siguiente manera:

    def to_representation(self, instance):

        # Este dict se utiliza para transformar las keys
        # con las que vienen los datos desde la api
        fields_map = {
            "CODIGO": "codigo",
            "NOMBREPERSONA": "nombrePersona",
            "APELLIDOPERSONA": "apellidoPersona",
        }

        for key, value in fields_map.items():
            # Se cambia el nombre el campo. Ej: NOMBREPERSONA => nombrePersona
            instance[value] = instance.pop(key)

        return instance

Cumple con la función pero no estoy seguro de que sea el mejor lugar para cambiarlo.

Hay una lib bastante usada que hace la conversión underscore <=> camelCase pero en este caso necesito definir manualmente las conversiones de los campos.

El otro problema tiene que ver con que Swagger me muestra el ejemplo de la Response con los campos en mayúscula. Tendría que ver dónde sobrescribir la generación del schema OpenAPI para que genere con los nombres que necesito. La librería que uso para generar el swagger es esta.

Gracias de antemano.

Probaste definiendo el atributo como vos queres y pasandole el source?

class EmpleadoSerializer(serializers.Serializer):

    codigo = serializers.IntegerField(source="CODIGO")

Hola Mati!

Sabes que intentamos eso hace unas semanas y llegamos a la (posiblemente errónea) conclusión de que source no funciona con Serializers que no hereden de ModelSerializer.

Viendo este test parece que si funciona y probablemente estabamos pasándole mal los datos al serializer.

El miércoles pruebo y actualizó el post.

Gracias!

1 me gusta

@matiar Pude probar y si bien funciona me quedan dudas sobre el comportamiento del serializer.

Cambié el serializer como dijiste:

class EmpleadoSerializer(serializers.Serializer):

    codigo = serializers.IntegerField(source="CODIGO")
    nombrePersona = serializers.CharField(source="NOMBREPERSONA")
    apellidoPersona = serializers.CharField(source="APELLIDOPERSONA")

El problema es que la validación del serializer falla:

'codigo': [ErrorDetail(string='Este campo es requerido.', code='required')], 
'nombrePersona': [ErrorDetail(string='Este campo es requerido.', code='required')],
'apellidoPersona': [ErrorDetail(string='Este campo es requerido.', code='required')]}]

Sin embargo, serializer.data contiene los datos serializados como yo los necesito! Y coincide con el test que linkeé en el otro comentario.

OrderedDict([('codigo', 1), ('nombrePersona', 'Marco'), ('apellidoPersona', 'Richetta'),])

Puede que me esté perdiendo de algo pero no le veo mucho sentido a usar el serializer sin la validación.

Por las dudas al serializer le paso los datos así:

empleados = [{
  "CODIGO": 1,
  "NOMBREPERSONA": "Marco",
  "APELLIDOPERSONA": "Richetta"
},
{
  "CODIGO": 2,
  "NOMBREPERSONA": "Marco",
  "APELLIDOPERSONA": "Richetta"
}]

EmpleadoSerializer(data=empleados, many=True)

Saludos!