danielgtaylor / danielgtaylor/python-betterproto

Integer keys in maps are not parsed correctly from JSON

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

Descripción

JSON requires that keys be represented as strings, however proto allows map keys to be any integral or string type. So when specifying a message with a JSON representation, integer keys must be represented as strings. These are not picked up by the `.from_json()` method, which just runs `json.loads(value)`.

Example:
The proto message
```
message MapTest {
map string_map = 1;
map int_map = 2;
}
```
with JSON example:
```json
{
"string_map": {
"hello": 2.3,
"there": 5.6
},
"int_map": {
"1": 7.9,
"2": 8.3
}
}
```
Would be parsed by better proto as
`MapTest(string_map={'hello': 2.3, 'there': 5.6}, int_map={'1': 7.9, '2': 8.3})`

To overcome this we just need to add a custom JSON decoder to the from_json method which looks for any keys which are integers.

An example implementation, adapted from this [link](https://stackoverflow.com/questions/45068797/how-to-convert-string-int-json-into-real-int-with-json-loads) would be:
```
class Decoder(json.JSONDecoder):
def decode(self, s):
result = super().decode(s) # result = super(Decoder, self).decode(s) for Python 2.x
return self._decode(result)

def _decode(self, o):
if isinstance(o, str):# or isinstance(o, unicode):
try:
return int(o)
except ValueError:
return o
elif isinstance(o, dict):
try:
return {int(k): self._decode(v) for k, v in o.items()}
except ValueError:
return {k: self._decode(v) for k, v in o.items()}
elif isinstance(o, list):
return [self._decode(v) for v in o]
else:
return o
```
We'd then run `json.loads(value, cls=Decoder)`

Guía de contribución

Abrir la guía de contribución

Línea de trabajo

The entry point named is .from_json(), which currently calls json.loads(value); start there and inspect how map fields are converted. Use the supplied MapTest JSON example to verify integer-key maps are reconstructed with integer keys while string-key maps remain unchanged, then run the project's existing tests.

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

Evaluación

Stack tecnológico
python
Área
api
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.