| 1344 | |
| 1345 | |
| 1346 | class JSONField(CharField): |
| 1347 | default_error_messages = { |
| 1348 | "invalid": _("Enter a valid JSON."), |
| 1349 | } |
| 1350 | widget = Textarea |
| 1351 | |
| 1352 | def __init__(self, encoder=None, decoder=None, **kwargs): |
| 1353 | self.encoder = encoder |
| 1354 | self.decoder = decoder |
| 1355 | super().__init__(**kwargs) |
| 1356 | |
| 1357 | def to_python(self, value): |
| 1358 | if self.disabled: |
| 1359 | return value |
| 1360 | if value in self.empty_values: |
| 1361 | return None |
| 1362 | elif isinstance(value, (list, dict, int, float, JSONString)): |
| 1363 | return value |
| 1364 | try: |
| 1365 | converted = json.loads(value, cls=self.decoder) |
| 1366 | except json.JSONDecodeError: |
| 1367 | raise ValidationError( |
| 1368 | self.error_messages["invalid"], |
| 1369 | code="invalid", |
| 1370 | params={"value": value}, |
| 1371 | ) |
| 1372 | if isinstance(converted, str): |
| 1373 | return JSONString(converted) |
| 1374 | else: |
| 1375 | return converted |
| 1376 | |
| 1377 | def bound_data(self, data, initial): |
| 1378 | if self.disabled: |
| 1379 | return initial |
| 1380 | if data is None: |
| 1381 | return None |
| 1382 | try: |
| 1383 | return json.loads(data, cls=self.decoder) |
| 1384 | except json.JSONDecodeError: |
| 1385 | return InvalidJSONInput(data) |
| 1386 | |
| 1387 | def prepare_value(self, value): |
| 1388 | if isinstance(value, InvalidJSONInput): |
| 1389 | return value |
| 1390 | return json.dumps(value, ensure_ascii=False, cls=self.encoder) |
| 1391 | |
| 1392 | def has_changed(self, initial, data): |
| 1393 | if super().has_changed(initial, data): |
| 1394 | return True |
| 1395 | # For purposes of seeing whether something has changed, True isn't the |
| 1396 | # same as 1 and the order of keys doesn't matter. |
| 1397 | return json.dumps(initial, sort_keys=True, cls=self.encoder) != json.dumps( |
| 1398 | self.to_python(data), sort_keys=True, cls=self.encoder |
| 1399 | ) |
no outgoing calls