0

While coding in python I'm getting an error: "Object of type myObject is not JSON serializable"

I tried to use some solutions I saw in other questions, but I didn't find many similarities between my code and the code in those questions, so I found it difficult to adapt the solutions in my code.

A part of my script is as follows. The error occurs in the last line of the first block:

import json
import os
from my_object import myObject
for a in A_set:
 if os.path.isfile(filename):
 with open(filename, 'r') as f:
 json_data = json.load(f)
 object_name = myObject.from_json(json_data)
 else:
 object_name = myObject(a)
 object_name.property_A = property_A
 object_name.property_C = []
 object_name.property_C_add_elements(var)
 with open(filename, 'w') as f:
 json.dump(object_name.to_json(), f)

In another python file is defined the class of 'myObject', where is also the method 'to_json()', which I'm calling in the line of code that produces the error.

class myObject:
 def __init__(self, name):
 self.name = name
 self.property_A = property_A
 self.property_B = property_B
 self.property_C = []
 def property_C_add_elements(self, var): 
 self.property_C.append(var)
 def to_json(self):
 return {
 'Name': self.name,
 'property A': self.property_A,
 'property B': self.property_B,
 'property C': self.property_C
 }
 @classmethod
 def from_json(cls, jason_data):
 object_name = myObject(jason_data['property A'])
 property_B = myObject(jason_data['property B'])
 c_list = []
 for var in jason_data['property C']:
 c_list.append(myObject(var))
 object_name.property_B = property_B
 object_name.property_C = c_list
 return object_name

I would be glad if I could get a solution to that problem. Thanks in advance.

asked Dec 24, 2018 at 14:53
2
  • 1
    The question lacks some required data according to [SO]: How to create a Minimal, Complete, and Verifiable example (mcve). For example, none of the files should compile: for a in A_set:, self.property_A = property_A. Please correct the question and also add the stacktrace. And edit the question, don't add comments. Commented Dec 24, 2018 at 15:07
  • Well, it's about a long script that is reading data from an excel file and wants to convert it in json form. It's a bit difficult to produce a minimal and complete code, but I'll give a try. However the second block of code is the complete code of my second file. Thanks for responding. Commented Dec 24, 2018 at 15:28

2 Answers 2

1

Here's a modified (and working) version of your code.

custom_object.py:

class CustomObject:
 @classmethod
 def from_json(cls, json_data):
 name = json_data["Name"]
 prop_a = json_data["PropertyA"]
 prop_b = json_data["PropertyB"]
 obj = cls(name, prop_a=prop_a, prop_b=prop_b)
 for var in json_data["PropertyC"]:
 obj.add_c_element(var)
 return obj
 def __init__(self, name, prop_a="", prop_b=""):
 self.name = name
 self.prop_a = prop_a
 self.prop_b = prop_a
 self.prop_c = list()
 def add_c_element(self, var):
 self.prop_c.append(var)
 def to_json(self):
 return {
 "Name": self.name,
 "PropertyA": self.prop_a,
 "PropertyB": self.prop_b,
 "PropertyC": self.prop_c,
 }

code.py:

#!/usr/bin/env python3
import sys
import json
import os
from custom_object import CustomObject
def main():
 filename = "./data.json"
 if os.path.isfile(filename):
 print("Attempting to load object from json file...")
 with open(filename, "r") as f:
 json_data = json.load(f)
 try:
 obj = CustomObject.from_json(json_data)
 except Exception as e:
 print(e)
 return
 print("Object: {:}\n Class: {:s}\n Attributes:" .format(obj, obj.__class__.__name__))
 for k, v in getattr(obj, "__dict__", dict()).items():
 print(" {:s}: {:}".format(k, v))
 else:
 print("Creating dummy object and saving to json...")
 obj = CustomObject("Object name", prop_a="object property a", prop_b="object property b")
 obj.add_c_element(1)
 obj.add_c_element("c element 2")
 with open(filename, "w") as f:
 json.dump(obj.to_json(), f)
 print("Done.")
if __name__ == "__main__":
 print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
 main()

Notes:

  • Corrected the errors (or added data that was missing)
  • Did some renames (class, objects, attributes) for clarity
  • Assumed that prop_a, prop_b are strings (not very important)
  • The (main) problem was in from_json function (I'm not sure what you tried to do there: why so many myObject instantiations, when there should have been only one). Anyway, what it does now:
    1. Gets name, prop_a, prop_b attributes from json_data (which is a dict)
    2. Constructs the object out of the 3 values from #1.
    3. Read the objects for prop_c, and adds them one by one (if any) to the object (by calling add_c_element)
  • Program searches for a file (with json contents):
    • If found, it tries to load the object from it and displays it
    • If not found, it creates a dummy object and dumps it in the file
  • This is one (not a very nice) way of doing things. It's meant to require minimum code changes, and it's also for learning purposes. The proper (scalable, general) way would be to extend JSONEncoder, JSONDecoder ([Python 3]: json - JSON encoder and decoder), but I feel that it would be a bit too advanced at this point

Output:

(py35x64_test) e:\Work\Dev\StackOverflow\q053914912>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" code.py
Python 3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32
Creating dummy object and saving to json...
Done.
(py35x64_test) e:\Work\Dev\StackOverflow\q053914912>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" code.py
Python 3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32
Attempting to load object from json file...
Object: <custom_object.CustomObject object at 0x00000230B6182C88>
 Class: CustomObject
 Attributes:
 prop_a: object property a
 prop_b: object property a
 name: Object name
 prop_c: [1, 'c element 2']
Done.
answered Dec 24, 2018 at 16:07
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much. The key was finally as you say in the classmethod, and my mistake was that the attributes should take their values from json_data rather than from a new object creation. Actually that was what I wanted. But as the error occurred few lines away from that point, I missed it. About the code of the script I will have a look and I will possibly use it as a part, or as a whole. Thanks again!
0

from the code you provided i can only speculate what types exactly your property_A, property_B, property_C variables/attributes are but

@classmethod
def from_json(cls, jason_data):
 object_name = myObject(jason_data['property A'])
 property_B = myObject(jason_data['property B'])
 c_list = []
 for var in jason_data['property C']:
 c_list.append(myObject(var))
 object_name.property_B = property_B
 object_name.property_C = c_list
 return object_name

Let's me speculate that your properties are Classinstances which have no "definition" of how they should be serialized into JSON. This is backed up by what you said :

"Object of type myObject is not JSON serializable"

I guess the problem is with the from_json() classmethod, there you should probably do smth. like :

EDITED:

Assuming that the __init__() method of your Class looks as follows

def __init__(self, name, property_A, property_B, property_C):
 self.name = name
 self.property_A = property_A
 self.property_B = property_B
 self.property_C = property_C 
 # property_C should be a list, you may want to add validation method 
 # which checks for correct types if it is preocess cirtical

I suggest the following:

@classmethod
def from_json(cls, jason_data):
 return cls(
 jason_data['name'],
 jason_data['property A'],
 jason_data['property B'],
 jason_data['property C']
 ) 

Furthermore i suggest, if it's possible, that you change your JSON Format, provided in your to_json() method by simply replacing the whitespaces from "property A" to "property_A" (same for other properties). In addition you can change "Name" to lowercase "name".

Why ? Because with this format, and my changed __init__() method you can convert your from_json() to the following utilizing unpacking operation :

@classmethod
def from_json(cls, jason_data):
 return cls(**json_data) 
answered Dec 24, 2018 at 15:11

3 Comments

Well, yes. The type of the error made me not to search carefully for the solution in my own code. Even the error was produced in a line that it was obvious that there wasn't any mistake. However not being familiar yet with the concept of the ool, I can make such a mistake. Now the code works properly. Thank you very much for responding, and for the time you spent.
Unfortunately, the code in the answer is even more incorrect than the one in the question.
If completely accurate: Yes i was quite superficial and hasty in the first version of my answer. I hope i clarified everything in the edit.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.