Skip to content

Commit

Permalink
[jsonish] Flesh out encoder a bit
Browse files Browse the repository at this point in the history
Initially, this is to handle disabling extras. Eventually, it could also
handle writing out to INI+JSON format.

XXX: Not sure how to handle the `allow_nan` arg, since it overlaps/
     conflicts with the `enable_extras` arg.
  • Loading branch information
wylee committed Jul 9, 2021
1 parent 97717c3 commit 165d612
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/jsonish/src/jsonish/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ def main(argv=None):
if out_file:
path = pathlib.Path(out_file)
with path.open("w") as fp:
encode_to_file(obj, fp, indent=indent)
encode_to_file(obj, fp, indent=indent, enable_extras=enable_extras)
else:
print(encode(obj, indent=indent))
print(encode(obj, indent=indent, enable_extras=enable_extras))


if __name__ == "__main__":
Expand Down
101 changes: 89 additions & 12 deletions src/jsonish/src/jsonish/encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,103 @@
"""
import datetime
import json
import functools

from .obj import JSONObject


__all__ = ["encode", "encode_to_file", "Encoder"]


def default(obj):
if isinstance(obj, JSONObject):
return dict(obj)
if isinstance(obj, datetime.datetime):
return obj.isoformat()
raise TypeError(f"Object of type {type(obj)} is not JSON serializable")
class Encoder(json.JSONEncoder):
def __init__(
self,
*,
skipkeys=False,
ensure_ascii=True,
check_circular=True,
allow_nan=True,
sort_keys=False,
indent=None,
separators=None,
default=None,
enable_extras=True,
):
super().__init__(
skipkeys=skipkeys,
ensure_ascii=ensure_ascii,
check_circular=check_circular,
allow_nan=allow_nan,
sort_keys=sort_keys,
indent=indent,
separators=separators,
default=default,
)
self.enable_extras = enable_extras

def jsonish_default(self, obj):
if self.enable_extras:
if isinstance(obj, JSONObject):
return dict(obj)
if isinstance(obj, datetime.datetime):
return obj.isoformat()
# Raise TypeError
return super().default(obj)

encode = functools.partial(json.dumps, default=default)
encode_to_file = functools.partial(json.dump, default=default)

def encode(
obj,
*,
cls=Encoder,
skipkeys=False,
ensure_ascii=True,
check_circular=True,
allow_nan=True,
sort_keys=False,
indent=None,
separators=None,
default=None,
enable_extras=True,
):
instance = cls(
skipkeys=skipkeys,
ensure_ascii=ensure_ascii,
check_circular=check_circular,
allow_nan=allow_nan,
sort_keys=sort_keys,
indent=indent,
separators=separators,
default=default,
enable_extras=enable_extras,
)
return instance.encode(obj)

class Encoder(json.JSONEncoder):
def default(self, obj):
return default(obj)

def encode_to_file(
obj,
fp,
*,
cls=Encoder,
skipkeys=False,
ensure_ascii=True,
check_circular=True,
allow_nan=True,
sort_keys=False,
indent=None,
separators=None,
default=None,
enable_extras=True,
):
instance = cls(
skipkeys=skipkeys,
ensure_ascii=ensure_ascii,
check_circular=check_circular,
allow_nan=allow_nan,
sort_keys=sort_keys,
indent=indent,
separators=separators,
default=default,
enable_extras=enable_extras,
)
iterable = instance.iterencode(obj)
for chunk in iterable:
fp.write(chunk)

0 comments on commit 165d612

Please sign in to comment.