diff --git a/rest_framework/utils/encoders.py b/rest_framework/utils/encoders.py index aa4542286..63811b839 100644 --- a/rest_framework/utils/encoders.py +++ b/rest_framework/utils/encoders.py @@ -5,6 +5,7 @@ Helper classes for parsers. import contextlib import datetime import decimal +import ipaddress import json # noqa import uuid @@ -45,6 +46,15 @@ class JSONEncoder(json.JSONEncoder): return float(obj) elif isinstance(obj, uuid.UUID): return str(obj) + elif isinstance(obj, ( + ipaddress.IPv4Address, + ipaddress.IPv6Address, + ipaddress.IPv4Network, + ipaddress.IPv6Network, + ipaddress.IPv4Interface, + ipaddress.IPv6Interface) + ): + return str(obj) elif isinstance(obj, QuerySet): return tuple(obj) elif isinstance(obj, bytes): diff --git a/tests/test_encoders.py b/tests/test_encoders.py index 953e5564b..74aebf8f2 100644 --- a/tests/test_encoders.py +++ b/tests/test_encoders.py @@ -1,3 +1,4 @@ +import ipaddress from datetime import date, datetime, timedelta, timezone from decimal import Decimal from uuid import uuid4 @@ -78,6 +79,48 @@ class JSONEncoderTests(TestCase): unique_id = uuid4() assert self.encoder.default(unique_id) == str(unique_id) + def test_encode_ipaddress_ipv4address(self): + """ + Tests encoding ipaddress IPv4Address object + """ + obj = ipaddress.IPv4Address("192.168.1.1") + assert self.encoder.default(obj) == str(obj) + + def test_encode_ipaddress_ipv6address(self): + """ + Tests encoding ipaddress IPv6Address object + """ + obj = ipaddress.IPv6Address("2001:0db8:85a3:0000:0000:8a2e:0370:7334") + assert self.encoder.default(obj) == str(obj) + + def test_encode_ipaddress_ipv4network(self): + """ + Tests encoding ipaddress IPv4Network object + """ + obj = ipaddress.IPv4Network("192.0.2.8/29") + assert self.encoder.default(obj) == str(obj) + + def test_encode_ipaddress_ipv6network(self): + """ + Tests encoding ipaddress IPv4Network object + """ + obj = ipaddress.IPv6Network("2001:4860:0000::0000/32") + assert self.encoder.default(obj) == str(obj) + + def test_encode_ipaddress_ipv4interface(self): + """ + Tests encoding ipaddress IPv4Interface object + """ + obj = ipaddress.IPv4Interface("192.0.2.8/29") + assert self.encoder.default(obj) == str(obj) + + def test_encode_ipaddress_ipv6interface(self): + """ + Tests encoding ipaddress IPv4Network object + """ + obj = ipaddress.IPv6Interface("2001:4860:4860::8888/32") + assert self.encoder.default(obj) == str(obj) + @pytest.mark.skipif(not coreapi, reason='coreapi is not installed') def test_encode_coreapi_raises_error(self): """