1

I have a python class that should return a json, it looks something like this:

class ScanThis():
    def__init__(self, test):
        data={}
        if test>5:
            data["amount"] = test
            self.json_data = json.dumps(data)
        else:
            data["fail"] = test
            self.json_data = json.dumps(data)

    def __str__(self):
        return self.json_data

and I'm trying to call it like so:

output= json.loads(ScanThis(8))
print(output["command"])

But I get this error:

TypeError: the JSON object must be str, bytes or bytearray, not 'ScanThis'

I believe my earlier clas returns an object of type ScanThis() rather than a JSon like I wanted. I just wanted to now how I'd fix this Thank you

PS: I apologise if this code is rough or invalid, it's not the actual code, just something similar I made up

Update: Again, this isn't the real code, it's just a small basic fragment of the actual code. There's a good reason I'm using a class, and a json is used cause data transfer over the internet is involved

5
  • 2
    You don't seem to have grasped the purpose of classes. If you don't want to return an instance of your class, don't use a class - use a function instead. Commented Jun 8, 2017 at 7:35
  • json.loads does not implicitly call __str__ on your ScanThis instance. Commented Jun 8, 2017 at 7:35
  • @deceze right, I honestly just realised how that works from the answer below Commented Jun 8, 2017 at 7:39
  • @Rawing I guess not, I've only ever written little python scripts that don't use classes....however a class was required for this one. Thanks Commented Jun 8, 2017 at 7:41
  • I should restate, this question is just a super basic lookalike of a section of the actual code, there's a good reason I need a class, trust me. Commented Jun 8, 2017 at 7:51

2 Answers 2

7

Use str(..)

You can't call json.loads on a ScanThis object directly. So that won't work. Like the error says, json.loads expects a str, bytes or bytearray object.

You can however use str(..) to invoke the __str__(self) method, and thus obtain the JSON data:

output = json.loads(str(ScanThis(8)))
#                   ^ get the __str__ result 

Use another method

That being said, it is usually a better idea to define a method, for instance to_json to obtain the JSON data, since now you have made str(..) return a JSON object. So perhaps a more elegant way to do this is the following:

class ScanThis():
    def__init__(self, test):
        data={}
        if test>5:
            data["amount"] = test
            self.json_data = json.dumps(data)
        else:
            data["fail"] = test
            self.json_data = json.dumps(data)

    def to_json(self):
        return self.json_data

and call it with:

output = json.loads(ScanThis(8).to_json())

Now you can still use __str__ for another purpose. Furthermore by using to_json you make it explicit that the result will be a JSON string. Using str for JSON conversion is of course not forbidden, but str(..) as a name, does not provide much guarantees about the format of the result whereas to_json (or another similar name) strongly hints that you will obtain JSON data.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, this worked perfectly for me, I didn't really understand the def __str__ part and honestly thought it got called automatically, really silly of me, thanks again!
0

I don't think you are wanting to use a class there at all. Instead, try using a function that returns a string. For example:

def scan_this(test):
    data={}
    if test>5:
        data["amount"] = test
        json_data = json.dumps(data)
    else:
        data["fail"] = test
        json_data = json.dumps(data)

    return json_data

output = json.loads(scan_this(8))

However!! Now you are just doing extra work for nothing? Why do you need to serialize a python dictionary as a json formatted string, and then load it back into a python dictionary straight away? While you are working with data in python, it's best to keep it as native data types, and only using the json module to either load from a string/file you already have, or serialize to a string/file for storage or transfer (eg sending over the internet).

4 Comments

I do know using a method would be far easier but the code I posted isn't the whole thing, the full code requires a class. Trust me, I'd prefer a method
Oh and the actual code does require sending this data over the internet. The part of my question that does the method calling is in a different class
@DrewU in that case you should have provided more context, including the info you just commented and the reason why you need all the code in the __init__ method of a class.
you're right, it seemed to have caused a lot of confusion, my apologies. And thank you

Your Answer

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.