Skip to content

REF: eliminate method _write() in json writers #36218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Oct 22, 2020
137 changes: 34 additions & 103 deletions pandas/io/json/_json.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from abc import ABC, abstractmethod
from collections import abc
import functools
from io import BytesIO, StringIO
Expand Down Expand Up @@ -110,7 +111,7 @@ def to_json(
path_or_buf.close()


class Writer:
class Writer(ABC):
def __init__(
self,
obj,
Expand Down Expand Up @@ -145,75 +146,51 @@ def _format_axes(self):
raise AbstractMethodError(self)

def write(self):
return self._write(
self.obj,
self.orient,
self.double_precision,
self.ensure_ascii,
self.date_unit,
self.date_format == "iso",
self.default_handler,
self.indent,
)

def _write(
self,
obj,
orient: Optional[str],
double_precision: int,
ensure_ascii: bool,
date_unit: str,
iso_dates: bool,
default_handler: Optional[Callable[[Any], JSONSerializable]],
indent: int,
):
iso_dates = self.date_format == "iso"
return dumps(
obj,
orient=orient,
double_precision=double_precision,
ensure_ascii=ensure_ascii,
date_unit=date_unit,
self.obj_to_write,
orient=self.orient,
double_precision=self.double_precision,
ensure_ascii=self.ensure_ascii,
date_unit=self.date_unit,
iso_dates=iso_dates,
default_handler=default_handler,
indent=indent,
default_handler=self.default_handler,
indent=self.indent,
)

@property
@abstractmethod
def obj_to_write(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add an annotation for this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

"""Object to write in JSON format."""

Copy link
Member

@jbrockmendel jbrockmendel Oct 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explicitly pass here

are the keys in the Dict necessarily str, or can they be any Index entries?

Copy link
Member Author

@ivanovmg ivanovmg Oct 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, actually the keys in the dictionary can be of IndexLabel type.
In FrameWriter the resulting dictionary keys can be tuples of strings in case of multicolumns.
In other cases the keys seem to be only strings.


class SeriesWriter(Writer):
_default_orient = "index"

@property
def obj_to_write(self):
if not self.index and self.orient == "split":
return {"name": self.obj.name, "data": self.obj.values}
else:
return self.obj

def _format_axes(self):
if not self.obj.index.is_unique and self.orient == "index":
raise ValueError(f"Series index must be unique for orient='{self.orient}'")

def _write(
self,
obj,
orient: Optional[str],
double_precision: int,
ensure_ascii: bool,
date_unit: str,
iso_dates: bool,
default_handler: Optional[Callable[[Any], JSONSerializable]],
indent: int,
):
if not self.index and orient == "split":
obj = {"name": obj.name, "data": obj.values}
return super()._write(
obj,
orient,
double_precision,
ensure_ascii,
date_unit,
iso_dates,
default_handler,
indent,
)


class FrameWriter(Writer):
_default_orient = "columns"

@property
def obj_to_write(self):
if not self.index and self.orient == "split":
obj_to_write = self.obj.to_dict(orient="split")
del obj_to_write["index"]
else:
obj_to_write = self.obj
return obj_to_write

def _format_axes(self):
"""
Try to format axes if they are datelike.
Expand All @@ -231,31 +208,6 @@ def _format_axes(self):
f"DataFrame columns must be unique for orient='{self.orient}'."
)

def _write(
self,
obj,
orient: Optional[str],
double_precision: int,
ensure_ascii: bool,
date_unit: str,
iso_dates: bool,
default_handler: Optional[Callable[[Any], JSONSerializable]],
indent: int,
):
if not self.index and orient == "split":
obj = obj.to_dict(orient="split")
del obj["index"]
return super()._write(
obj,
orient,
double_precision,
ensure_ascii,
date_unit,
iso_dates,
default_handler,
indent,
)


class JSONTableWriter(FrameWriter):
_default_orient = "records"
Expand Down Expand Up @@ -330,30 +282,9 @@ def __init__(
self.orient = "records"
self.index = index

def _write(
self,
obj,
orient,
double_precision,
ensure_ascii,
date_unit,
iso_dates,
default_handler,
indent,
):
table_obj = {"schema": self.schema, "data": obj}
serialized = super()._write(
table_obj,
orient,
double_precision,
ensure_ascii,
date_unit,
iso_dates,
default_handler,
indent,
)

return serialized
@property
def obj_to_write(self):
return {"schema": self.schema, "data": self.obj}


@deprecate_kwarg(old_arg_name="numpy", new_arg_name=None)
Expand Down