Error: Object of type IntervalStrategy is not JSON serializable when add `indent` to verticalize json

Question:

I want to save a dataclass to a json file and save it, it is ok now without adding paramenter indent.

class EnhancedJSONEncoder(json.JSONEncoder):
        def default(self, o):
            if dataclasses.is_dataclass(o):
                return dataclasses.asdict(o)
            # return super().default(o)

model_json = json.dumps(model_args, cls=EnhancedJSONEncoder)

model_args is a dataclass object, take a simple example,

from dataclasses import dataclass
@dataclass
class Model_args:
    x: str
model_args = Model_args(x="bar")

However, when I add indent, for example,

model_json = json.dumps(model_args, cls=EnhancedJSONEncoder,indent=4)

it shows

raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type IntervalStrategy is not JSON serializable

I want to save to json file vertically(make it looks better)

 with open("model_args.json", "w") as f:
        f.write(model_json)
Asked By: 4daJKong

||

Answers:

model_json = json.dumps(model_args, cls=EnhancedJSONEncoder)

model_json is a string format, actually,like "{x="bar"}"
if you want to save it as dict and add indent parameter, converting it to dict format firstly by json.loads()

model_str = json.dumps(model_args, cls=EnhancedJSONEncoder)
model_json = json.loads(model_str)
with open(json_path, "w") as f:
    json.dump(model_json, f, indent=4)
Answered By: 4daJKong

There is nothing wrong with your approach using json.JSONEncoder, but as a long-term solution, to avoid code bloat when introducing other (more complex) types such as datetime, I would suggest looking into an existing library such as dataclass-wizard, which provides built-in support for saving a dataclass instance to a file, e.g. such as with JSONFileWizard:

from dataclasses import dataclass
from dataclass_wizard import JSONFileWizard


@dataclass
class ModelArgs(JSONFileWizard):
    x: str


ma = ModelArgs(x="bar")

## TODO
json_path = './my_file.out.json'

ma.to_json_file(json_path, indent=4)

Contents of my_file.out.json:

{
    "x": "bar"
}

Disclaimer: I am the creator and maintainer of this library.

Answered By: rv.kvetch