Last updated: Apr 10, 2024
Reading timeยท4 min
The Python "ValueError: malformed node or string" occurs for 3 main reasons:
ast.literal_eval()
method.json.loads()
instead).To solve the error, use the str()
class to convert the value to a string or
make sure to only call the ast.literal_eval()
method with strings.
Here is an example of how the error occurs.
import ast a_dict = { 'first': 'bobby', 'last': 'hadz', } # โ๏ธ ValueError: malformed node or string: {'first': 'bobby', 'last': 'hadz'} print(ast.literal_eval(a_dict))
We called the ast.literal_eval method with a dictionary instead of a string which caused the error.
The method evaluates a string that contains a Python literal.
The string may consist of the following objects:
Note that the method expects to get called with the string representation of the given object, not the object itself (not a dictionary, list or set).
Here is an example of using the ast.literal_eval()
method correctly.
import ast a_str = '''{ "first": "bobby", "last": "hadz" }''' result = ast.literal_eval(a_str) print(result) # ๐๏ธ {'first': 'bobby', 'last': 'hadz'} print(type(result)) # ๐๏ธ <class 'dict'>
Notice that we passed a string to the method and not a dictionary.
The string in the example is a valid dictionary, so it gets parsed to a native
Python dict
object by the literal_eval()
method.
ast.literal_eval()
One way to solve the error is to use the
str() class to convert the object to a
string in the call to the ast.literal_eval()
method.
import ast a_dict = { 'first': 'bobby', 'last': 'hadz', } result = ast.literal_eval(str(a_dict)) print(result) # ๐๏ธ {'first': 'bobby', 'last': 'hadz'} print(type(result)) # ๐๏ธ <class 'dict'>
We used the str()
class to convert the dictionary to a string in the call to
the method.
No error is raised because the method is called with a string argument.
However, the conversion shouldn't be necessary and could lead to performance issues if the given value is a very large dictionary or list.
literal_eval()
An alternative approach is to use the
isinstance() function to check
if the value is a string before calling the ast.literal_eval()
method.
import ast a_dict = { 'first': 'bobby', 'last': 'hadz', } if isinstance(a_dict, str): result = ast.literal_eval(a_dict) else: result = a_dict print(result) # ๐๏ธ {'first': 'bobby', 'last': 'hadz'} print(type(result)) # ๐๏ธ <class 'dict'>
We only call the ast.literal_eval()
method if the value is a string.
Otherwise, we set the result
variable to the value.
This helps us avoid the redundant conversion to string.
I've written a detailed article on how to convert the string representation of a list to a list.
The code samples also apply to dictionaries.
Note that calling the ast.literal_eval()
method with a string that is not a
valid Python object would raise an error.
import ast a_str = '''{ "first": "bobby", "last": "hadz", "hello" "world" }''' # โ๏ธ ERROR result = ast.literal_eval(a_str)
Notice that the last key-value pair in the dictionary is not separated by a colon.
Trying to parse an invalid object causes an error.
json.loads()
method if parsing JSON dataMake sure you aren't using the ast.literal_eval()
method to parse a JSON
string.
Here is an example of how this causes an error.
import ast a_str = '''{ "first": "bobby", "last": "hadz", "is_programmer": true, "salary": null }''' # โ๏ธ ValueError: malformed node or string on line 4: result = ast.literal_eval(a_str)
The string is valid JSON, however, it should not be parsed using
ast.literal_eval()
.
JSON strings contain lowercase boolean values (true
and false
) and Python
booleans have a capital first letter (True
and False
).
Similarly, we have null in JSON vs None in Python.
Instead, you should use the json.loads()
method to convert the JSON string to
a native Python object.
import json a_str = '''{ "first": "bobby", "last": "hadz", "is_programmer": true, "salary": null }''' result = json.loads(a_str) # ๐๏ธ {'first': 'bobby', 'last': 'hadz', 'is_programmer': True, 'salary': None} print(result) print(type(result)) # ๐๏ธ <class 'dict'>
The json.loads() method parses a JSON string into a native Python object.
I've written a detailed article on how to convert a JSON string to a native Python object.
If you need to convert the string representation of an object to a Python object, check out the following article instead.
You can learn more about the related topics by checking out the following tutorials: