danielgtaylor / danielgtaylor/python-betterproto

Integer keys in maps are not parsed correctly from JSON

Offen
#235 5 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
bug
Vorherrschende Sprache
Python
Sterne
1.8k
Forks
234
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Beschreibung

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)`

Beitragsleitfaden

Beitragsleitfaden öffnen

Rechercherichtung

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.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
api
Issue-Typ
Bug
Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Aktivitätsstatus
Veraltet
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
45/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.