Convert bool values to string in json.dumps() - python

I'm trying to convert a python dict into json, however the API I'm accessing doesn't take bool value instead it uses "true"/"false" string.
Example:
dct = { "is_open": True }
json.dumps(dct)
currently gives a bool output: { "is_open": true }
but what I want is lower-case string output:
{ "is_open": "true" }
I tried json.dumps(dct, cls=MyEncoder) but it doesn't work, only non-native object get passed to MyEncoder default.
class MyEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, bool):
return str(o).lower()
return super(MyEncoder, self).default(o)
Any help would be great.
(Btw this is not my API I'm accessing, so I can't modify the API to access true false value instead of the string alternative.)

If it were me, I'd convert the Python data structure to the required format and then call json.dumps():
import json
import sys
def convert(obj):
if isinstance(obj, bool):
return str(obj).lower()
if isinstance(obj, (list, tuple)):
return [convert(item) for item in obj]
if isinstance(obj, dict):
return {convert(key):convert(value) for key, value in obj.items()}
return obj
dct = {
"is_open": True
}
print (json.dumps(dct))
print (json.dumps(convert(dct)))
Output:
{"is_open": true}
{"is_open": "true"}

Related

flask-marshmallow validation on field data not working

Hi I made my dto something like this
class MyRequestDto(ma.Schema):
#pre_load
def wrap_data(self, in_data, **kwargs):
return {"rooms": in_data}
rooms = ma.Dict(ma.String, ma.Dict(ma.Integer, ma.String))
and I want to send request something like this :
{
"1faf8f07-2977-180e-7bc2-b5adf8badasda": {"student_id":11210687,"room_id":"100"}
}
but getting error like this
{
"rooms": {
"1faf8f07-2977-180e-7bc2-b5adf8badasda": {
"value": {
"student_id": {
"key": [
"Not a valid integer."
]
},
"room_id": {
"key": [
"Not a valid integer."
]
}
}
}
}
}
What I can do to pass data correctly in the required format?
Integer type supports cast.
From the documentation:
class marshmallow.fields.Integer(*, strict: bool = False, **kwargs)[source]
An integer field.
Parameters
strict – If True, only integer types are valid. Otherwise, any value castable to int is valid.
kwargs – The same keyword arguments that Number receives.
So try:
class MyRequestDto(Schema):
#pre_load
def wrap_data(self, in_data, **kwargs):
return {"rooms": in_data}
rooms = Dict(String, Dict(String, Integer))
It will automatically handle the str for room_id.
If you want to keep room_id as str then you need to define a Custom Field.
Example:
class CustomField(Field):
def _serialize(self, value, attr, obj, **kwargs):
if isinstance(value, (str, int)):
return value
raise ValidationError("Value is not int or str")
def _deserialize(self, value, attr, data, **kwargs):
if isinstance(value, (str, int)):
return value
raise ValidationError("Value is not int or str")
class MyRequestDto(Schema):
#pre_load
def wrap_data(self, in_data, **kwargs):
return {"rooms": in_data}
rooms = Dict(String, Dict(String, CustomField))

How to define dictionary whose values are showing of what type should be a property, which name is used as key?

I am working on application, which should verify a JSON.
The properties are of different types (numeric, string, date), that is why I have not only to verify the presence of the properties, but also whether their value is of the required type.
That is why I would like to define dictionary, which key will be the name of the property and the value will be the type, that this property should be of (with the operator isinstance or in some other way). But I do not know how to implement this in Python. Something like this:
map_of_property_to_classes: Dict[str, any]
class_name = map_of_property_to_classes["property_name"]
print(isinstance("property_name", class_name))
Can somebody give a hint?
Are you looking for something like the below?
from typing import Dict
def validate(data: Dict, meta_data: Dict) -> None:
for k, v in data.items():
if isinstance(v, meta_data[k]):
print('OK')
else:
print(f'{v} must be of type {meta_data[k]}')
_data = {'x': 12, 'name': 12}
_meta_data = {'x': int, 'name': str}
validate(_data,_meta_data)
output
OK
12 must be of type <class 'str'>
I'm not sure if this answer your question but I have written a script which read a JSON file and return a dict.
Here's the JSON file:
"Config":{
"programming_languages" : {"_type" : "dict", "value" : {
"py" : "python",
"js" : "javascript",
"txt" : "plain",
"md" : "markdown",
"cs" : "csharp"
}},
"noEditTypes": {"_type" : "set", "value" : ["pdf", "jpg", "jpeg", "png"]}
}
And here's the python Code:
#staticmethod
def configParser():
with open("data/data.json", "r") as f:
data = json.load(f).get("Config")
outData = {}
for i in data:
valTypeName = data[i].get("_type")
if valTypeName == "set":
valType = set
elif valTypeName == "str":
valType = str
elif valTypeName == "int":
valType = int
elif valTypeName == "list":
valType = list
elif valTypeName == "dict":
valType = dict
else:
raise Exception("Unknown Type: {}".format(valTypeName))
valvalue = data[i].get("value")
outData[i] = valType(valvalue)
return outData
I think if you modify this code a bit it would also work for your intended use.

Pylint says: W0233: __init__ method from a non direct base class 'Nested' is called (non-parent-init-called)

I'm newbie in programming and python also. When I try to wrap my data structure to class in order not to make list or dict iterating, I get the pylint error message:
W0233: __init__ method from a non direct base class 'Nested' is called (non-parent-init-called)
Is there any best "pythonic" way to do this?
My json data is so:
{
"template" : [
{
"folder" : "/Users/SA/Documents/GIT/rs-finance/templates",
"basetpl" : "tpl.docx",
"header" : "header_tpl.docx",
"table" : "table_tpl.docx",
"footer" : "footer_tpl.docx"
}
],
"export" : [
{
"folder" : "/Users/SA/Documents/GIT/rs-finance/export",
"name" : "result.docx"
}
]
}
And when I load this data (or its piece) to dict or list variable & try to wrap it with this class:
class Nested ():
def __init__(self, data):
if isinstance (data, dict):
for key, value in data.items():
if isinstance(value, (float, int, str)):
setattr(self, key, value)
else:
setattr(self, key, Nested(value))
if isinstance(data, list):
for item in data:
self.__init__(item)
The Pylint doesn't like my last line 😳
Calling __init__ explicitly isn't wrong, but it is odd, and that's all Pylint is warning you about.
A better practice is to write a separate recursive function that does what you want, then call that from __init__.
class Nested:
def __init__(self, data):
self.recursive(data)
def recursive(self, data):
if isinstance(data, dict):
for key, value in data.items():
if isinstance(value, (float, int, str)):
setattr(self, key, value)
else:
setattr(self, key, Nested(value))
elif isinstance(data, list):
for item in data:
self.recursive(item)

i want to parse the json file only if it matches to the specified structure in python

The structure of the json file has to be specified in the python program. the program should parse any input json file only if it matches to that structure. I'm new to python please help me!
sample json file may be like this
"person":{
"sex":{
"name": "XXX",
"address":[
{
"street": "abc",
"area" : "xyz",
},
],
}
the json files having this structure only has to be parsed, if there is one extra field other than these shouldn't be parsed.
Please help me out Thanks in advance
With these two functions you can check all keys in your dictionaries
if the keys are equal it will return True
def get_keys(obj, keys=[]):
''' creates a list with all keys from a nested, json valid dictionary '''
if isinstance(obj, dict):
for k, v in obj.items():
if isinstance(v, dict) or isinstance(v, list) and all(isinstance(item,dict) for item in v):
keys.append(k)
return get_keys(v, keys)
else:
keys.append(k)
#calls get_keys with the list of keys as object this will trigger the else statement and return the object
else: return get_keys(keys)
elif isinstance(obj, list) and all(isinstance(item, dict) for item in obj):
#checks if obj is a list and if all obj in a list are dictionaries
for dct in obj:
for k, v in dct.items():
if isinstance(v, dict) or isinstance(v, list) and isinstance(v[0], dict):
keys.append(k)
return get_keys(v, keys)
else:
keys.append(k)
#same as above
else: return get_keys(keys)
else:
return obj
def has_same_structure(dct_1,dct_2):
''' checks if two (nested) dictionaries have the same keys '''
if get_keys(dct_1) == get_keys(dct_2, keys=[]):
return True
else:
return False
I hope this helps

dbus Variant: How to preserve boolean datatype in Python?

I've been experimenting with dbus lately. But I can't seem to get my dbus Service to guess the correct datatypes for boolean values. Consider the following example:
import gtk
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
class Service(dbus.service.Object):
def __init__(self):
bus_name = dbus.service.BusName("org.foo.bar", bus = dbus.SessionBus())
dbus.service.Object.__init__(self, bus_name, "/org/foo/bar")
#dbus.service.method("org.foo.bar", in_signature = "a{sa{sv}}",
out_signature = "a{sa{sv}}")
def perform(self, data):
return data
if __name__ == "__main__":
DBusGMainLoop(set_as_default = True)
s = Service()
gtk.main()
This piece of code creates a dbus service that provides the perform method which accepts one parameter that is a dictionary which maps from strings to other dictionaries, which in turn map strings to variants. I have chosen this format because of the format my dictionaries are in:
{
"key1": {
"type": ("tuple", "value")
},
"key2": {
"name": "John Doe",
"gender": "male",
"age": 23
},
"test": {
"true-property": True,
"false-property": False
}
}
When I pass this dictionary through my service, the boolean values are converted to integers. In my eyes, the check should not be that difficult. Consider this (value is the variable to be converted to a dbus type):
if isinstance(value, bool):
return dbus.Boolean(value)
If this check is done before checking for isinstance(value, int) then there would be no problem.
Any ideas?
I'm not sure which part you're having difficulty with. The types can easily be cast from one form to another, as you show in your example dbus.Boolean(val). You can also use isinstance(value, dbus.Boolean) to test if the value is a dbus boolean, not an integer.
The Python native types are converted into dbus types in order to enable communicate between DBus clients and services written in any language. So any data sent to / received from a DBus service will consist of dbus.* data types.
def perform(self, data):
for key in ['true-property', 'false-property']:
val = data['test'][key]
newval = bool(val)
print '%s type: %s' % (key, type(val))
print 'is dbus.Boolean: %s' % isinstance(val, dbus.Boolean)
print 'Python:', newval
print ' Dbus:', dbus.Boolean(newval)
return data
Output:
true-property type: <type 'dbus.Boolean'>
is dbus.Boolean: True
Python: True
Dbus: 1
false-property type: <type 'dbus.Boolean'>
is dbus.Boolean: True
Python: False
Dbus: 0

Categories

Resources