danielgtaylor / danielgtaylor/python-betterproto

Default values are not serialized in oneofs when calling .to_dict() or .to_json() (which is different behaviour from official protobuf impl)

Abierto
#109 4 comentarios 0 reacciones 0 asignados Ver en GitHub
bug medium priority
Lenguaje dominante
Python
Estrellas
1.8k
Forks
234
Métricas de merge de PR
Sin PR fusionados en 30 d

Descripción

# Consider this protobuf message:

```
message OneOfDemo{
oneof value_type {
bool bool_value = 1;
int64 int64_value = 2;
}
}
```

# Using the official protobuf codegen and library (libprotoc 3.12.3):

```
from google.protobuf.json_format import MessageToDict

# Official protobuf:
print("True: ", json.dumps(MessageToDict(OneOfDemo(bool_value=True))))
print("False:", json.dumps(MessageToDict(OneOfDemo(bool_value=False))))
print("1: ", json.dumps(MessageToDict(OneOfDemo(int64_value=1))))
print("0: ", json.dumps(MessageToDict(OneOfDemo(int64_value=0))))

Output:
True: {"boolValue": true}
False: {"boolValue": false}
1: {"int64Value": "1"}
0: {"int64Value": "0"}
```

# Using betterproto (1.2.5)

```
# Generated code:
@dataclass
class OneOfDemoBetter(betterproto.Message):
bool_value: bool = betterproto.bool_field(1, group="value_type")
int64_value: int = betterproto.int64_field(2, group="value_type")

print("True: ", OneOfDemoBetter(bool_value=True).to_json())
print("False:", OneOfDemoBetter(bool_value=False).to_json())
print("1: ", OneOfDemoBetter(int64_value=1).to_json())
print("0: ", OneOfDemoBetter(int64_value=0).to_json())

Output:
True: {"boolValue": true}
False: {}
1: {"int64Value": "1"}
0: {}
```

This obviously leads to the following inconsistency:

```
od = OneOfDemoBetter(bool_value=False)
print(betterproto.which_one_of(od, "value_type"))

od2 = OneOfDemoBetter().from_json(od.to_json())
print(betterproto.which_one_of(od2, "value_type"))

Output:
('bool_value', False)
('', None)
```

# Misc

* Python 3.8.1
* I love what you are trying to do with this project btw - the official generated protobuf code is AWEFUL and this is a HUGE step forwards. This one difference in behaviour is blocking wholesale adoption of your project unfortunately
* Tangentially related ideas and observations
* Would it make sense to have values in the oneof be declared `Optional`? (ie: `bool_value: Optional[bool]`) since only one is expected to be set? Personally I would prefer this but I can understand if its getting too far away from the idea of "there are no nulls in proto3".
* `.to_json()` is missing the `casing` arg (and `include_default_values`) from `.to_dict()`
* Stretch/wishlist: personally I would find it super valuable if there were some way to default to `Casing.SNAKE` for all `.to_json()` operations automatically. Perhaps something like a default option you could specify on a per message basis?

Great work on this project! Keep it up!

Guía de contribución

Abrir la guía de contribución

Línea de trabajo

Reproduzca el problema con el ejemplo OneOfDemo del informe, comparando to_dict() y to_json() para valores oneof false y zero. Rastree los puntos de entrada de la serialización y verifique que el campo oneof seleccionado siga presente durante la serialización y deserialización, incluido el recorrido de ida y vuelta de which_one_of().

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
python
Área
tooling
Tipo de issue
Error
Dificultad
3/5
Tiempo estimado
1-2 días
Estado de actividad
Estancado
Claridad
Bien especificado
Aptitud para principiantes
45/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.