I am trying to simulate the problem statement using the below program:
import json
class System:
def __init__(self):
self.model = "abc"
self.fwVersion = "123"
self.prevfwVersion = "456"
self.safemodeVersion = "5756"
def __setitem__(self, key, val):
self.__dict__[key] = val
def __getitem__(self, key):
return self.__dict__[key]
def toJSON(self):
return self.__dict__
class Mainwall:
def __init__(self):
self.system = System()
def __setitem__(self, key, val):
self.__dict__[key] = val
def __getitem__(self, key):
return self.__dict__[key]
def toJSON(self):
return self.__dict__
class ComplexEncoder(json.JSONEncoder):
def default(self, obj):
if hasattr(obj, 'toJSON'):
return obj.toJSON()
else:
return json.JSONEncoder.default(self, obj)
fw = Mainwall()
def my_print():
print(json.dumps(fw.toJSON(), cls=ComplexEncoder, indent=4))
if __name__ == '__main__':
my_print()
Since python dictionary does not preserve the insertion order , the output of the above program is always will have the different key order.
Say, first time it prints:
{
"system": {
"safemodeVersion": "5756",
"prevfwVersion": "456",
"fwVersion": "123",
"model": "abc"
}
}
Second time it prints:
{
"system": {
"fwVersion": "123",
"prevfwVersion": "456",
"safemodeVersion": "5756",
"model": "abc"
}
}
But, in the output I would like to preserve the order in which the class members are initialized. i.e., Exactly as below:
{
"system": {
"model": "abc",
"fwVersion": "123",
"prevfwVersion": "456",
"safemodeVersion": "5756",
}
}
How to achieve the expected output for the same example using OrderedDict() or some other method?
There is a work-around I made for you. I invite you to look into the System() class. I created an OrderedDict() instead of four self attributes. Then, in you method toJSON(self):, instead of returning the self.__dict__ attributes, I am returning the OrderedDict() I set earlier.
class System:
def __init__(self, model='abc', fwVersion='123', prevfwVersion='456', safemodeVersion='5756'):
self.my_ordered_dict = OrderedDict()
self.my_ordered_dict['model'] = model
self.my_ordered_dict['fwVersion'] = fwVersion
self.my_ordered_dict['prevfwVersion'] = prevfwVersion
self.my_ordered_dict['safemodeVersion'] = safemodeVersion
# self.model = "abc"
# self.fwVersion = "123"
# self.prevfwVersion = "456"
# self.safemodeVersion = "5756"
def __setitem__(self, key, val):
self.__dict__[key] = val
def __getitem__(self, key):
return self.__dict__[key]
def toJSON(self):
return self.my_ordered_dict
This System() class instead of the one above, with the same code, outputs...
{
"system": {
"model": "abc",
"fwVersion": "123",
"prevfwVersion": "456",
"safemodeVersion": "5756"
}
}
upgrading to python 3.6 solved the problem.
Related
{
"originProduct": {
"statusType": "SALE",
"saleType": "NEW",
"leafCategoryId": "50002322",
"name": "Jabra SPEAK 750 블루투스스피커/스피커폰/음성회의스피커폰/JABRA / 자브라 공식정품",
"images": {
"representativeImage": {
"url": "http://shop1.phinf.naver.net/20221220_24/1671526069078ktTkT_JPEG/4172814067322311_1866531646.jpg"
},
"optionalImages": [
{
"url": "http://shop1.phinf.naver.net/20221220_2/16715260691656YLKl_JPEG/4172814155176861_2054960625.jpg"
},
{
"url": "http://shop1.phinf.naver.net/20221220_5/1671526069249T4zWk_JPEG/4172814239069085_483270929.jpg"
}
]
}
}
I have a json file like the one above.
def open(self):
with open(self.json_file,"r",encoding='utf-8-sig') as f:
item_dic=json.load(f)
return item_dic
def save(self,item_dic):
with open(self.json_file,'w',encoding='utf-8-sig') as f:
json.dump(item_dic,f,indent=4,ensure_ascii=False)
def basic_data(self):
item_dic=self.open()
statusType = "SALE" #상품상태
saleType = "NEW" #판매유형
leafCategoryId = self.soup()["category"]["categoryId"] #카테고리넘버
name = self.soup()["name"] #상품명
salePrice = self.soup()["salePrice"] #판매가
stockQuantity = 100 #재고수량
basic_data = {
"statusType": statusType,
"saleType": saleType,
"leafCategoryId": leafCategoryId,
"name": name,
"salePrice": salePrice,
"stockQuantity": stockQuantity,
}
try:
del item_dic["originProduct"]["productLogistics"]
del item_dic["originProduct"]["saleStartDate"]
del item_dic["originProduct"]["saleEndDate"]
except:
pass
item_dic["originProduct"].update(basic_data)
self.save(item_dic)
In the basic_data function, we create a json type and implement a function that loads and updates a json file.
I want to combine the def open function and the def save function into one so that they can function.
def save_func(self,key,new_data):
## key -> parameter like ["originProduct"] ##
with open(self.json_file,"r",encoding='utf-8-sig') as f:
item_dic=json.load(f)
item_dic.[key].update(basic_data)
with open(self.json_file,'w',encoding='utf-8-sig') as f:
json.dump(item_dic,f,indent=4,ensure_ascii=False)
The problem is that there is no problem if the argument to be passed as key is ["originProduct"], but when two or three are passed, there is a problem whether to get the key value inside the function.
From what I can tell, it seems like you are looking to overload a function and update values in your item_dict based on what is being given to you. I will warn you, I am not used to overloading in python so there may be better ways to do this. However, I made a script that updates based on the data to be used as an example, but I am not sure if I am doing more than you need, but I feel that the answer is in there somewhere.
main_list = {
"key1": 43,
"key2": 54,
"key3": 95
}
def update(param1, param2 = None):
if isinstance(param1, dict): # If parameter 1 is a dictionary, we have our key/data in param1
update_from_dictionary(param1)
elif isinstance(param1, list) and isinstance(param2, list): # If parameter 1 and 2 are both arrays, we were fed keys in param1 and values in param2
update_values(param1, param2)
else: # Assuming that if the above two conditions are not met, we were fed a singular key and value pair
update_value(param1, param2)
def update_values(keys, values):
# Handle updating your dictionary object by looping key/value pair using a for loop
for i in range(0, len(keys)):
main_list[keys[i]] = values[i]
def update_value(key, value):
main_list[key] = value
def update_from_dictionary(dictionary):
for i in dictionary.keys():
main_list[i] = dictionary[i]
def main():
print(main_list)
data = {
"key1": 1,
"key2": 2
}
update(data)
print(main_list)
if __name__ == "__main__":
main()
i have a pandas dataframe that contains Objects of Cell, this is the class:
class Cell:
def __init__(self, data, coordinates, cell_id):
self._cell_id = cell_id
self._coordinates = coordinates
self._data = data
#property
def data(self) -> str:
return self._data
#property
def coordinates(self) -> dict:
return self._coordinates
#property
def cell_id(self) -> str:
return self._cell_id
#property
def empty(self) -> bool:
if self._data == 0:
return False
return self._data is None or self._data == ""
def set_data(self, data):
self._data = data
def __repr__(self):
return self._data
every item in the dataframe is represented by this class.
but when trying to transform this class to json, for some reason not all values from the class are exported to the json.
this is the command i am using:
json.loads(df.to_json())
and the results looks like this:
{
"header_col1": {
"1": {
"cell_id": "705f7e89-abd4-4f7b-adfb-802010016546",
"data": "7579"
},
"2": {
"cell_id": "f04f3168-95d1-45f6-bb41-fc572736aeb7",
"data": "6207"
}
},
"header_col2": {
"1": {
"cell_id": "03fce322-a6d4-40ba-abbe-4f2558e6805f",
"data": "some text"
},
"2": {
"cell_id": "7b373ba4-e062-4881-99c6-2beaa0a20bcb",
"data": "some text"
},
}
}
i expected it to export all other fields of the Cell object as well, i don't understand why it exports only those 2 specific fields..
to reproduce the issue you can try using this:
mat = []
cords = {"x": 0, "y": 0, "w": 0, "h": 0}
for i in range(5):
row = []
for b in range(3):
row.append(Cell(cell_id=f"id_{b}", coordinates=cords, data=f"data_{b}"))
mat.append(row)
df = pd.DataFrame(mat)
json.loads(df.to_json())
the problem exists on pandas 1.3 on python3.9
upgrading to pandas 1.43 solves the issue
I have mongodb document as an array and need to create json file in python.
mongodb document looks like
db.mappedfields.insertMany(
[
{ sourceAttribute: "first_name",
domainAttribute: "First_Name"},
{ sourceAttribute: "last_name",
domainAttribute: "Last_Name"}
]
Code tried
class create_dict(dict):
def __init__(self):
self = dict()
def add(self, key, value):
self[key] = value
mydict = create_dict()
i = 1
for key in mycol.find():
mydict.add(i, ({key['sourceAttribute']:key['domainAttribute']}))
i = i+1
json_data = json.dumps(mydict, indent=2, sort_keys=True)
Output getting
{
"1": {
"first_name": "First_Name"
},
"2": {
"last_name": "Last_Name"
}
}
Expected Output
{
"first_name": "First_Name",
"last_name": "Last_Name"
}
import json
import pymongo
class create_dict(dict):
# __init__ function
def __init__(self):
self = dict()
# Function to add key:value
def add(self, key, value):
self[key] = value
mydict = create_dict()
i = 1
for key in mycol.find():
mydict.add(i, ({key['input']:key['output']}))
i = i+1
json_data = json.dumps(mydict, indent=2, sort_keys=True)
json_data1 = json.loads(json_data)
dictlist = []
for key, value in json_data1.items():
dictlist.append(value)
print(dictlist)
result = {}
for d in dictlist:
result.update(d)
print(result)
I'm a bit new to Python Classes. I worked with python but not extensively with classes. So here is what I'm trying to do, is to read a JSON and convert the elements and nodes to a class and object, so I call functions to get values from the JSON.
{
"datamap": {
"version": "1.0",
"sourceProvider": "example_provider",
"logicalTables": [
{
"name": "region_table_one",
"physicalTable": "dbo_parent_user",
"logicalColumns": [
{
"name": "UID",
"physicalColumnName": "uid_number",
"displayName": "U Number",
"logicalDataType": "integer",
"inputType": {
"inputAction": "number",
"multiSelect": false
},
},
{
"name": "UID1",
"physicalColumnName": "uid_number1",
"displayName": "U Number1",
"logicalDataType": "integer",
"inputType": {
"inputAction": "number",
"multiSelect": false
},
},
]
},
{
"name": "region_table_two",
"physicalTable": "dbo_user_two",
"logicalColumns": [
{
"name": "UID2",
"physicalColumnName": "uid_number2",
"displayName": "U Number2",
"logicalDataType": "integer",
"inputType": {
"inputAction": "number",
"multiSelect": false
},
},
{
"name": "UID3",
"physicalColumnName": "uid_number3",
"displayName": "U Number3",
"logicalDataType": "integer",
"inputType": {
"inputAction": "number",
"multiSelect": false
},
},
]
}
]
}
}
The Python Class I wrote:
import json
class DataMap(object):
def __init__(self):
with open('datamap.json') as f:
self.__dict__ = json.load(f)
def get_logical_table(self, tableName):
if self.datamap['logicalTables']['name'] == tableName:
return datamap['logicalTables']['name']
obj = DataMap()
print(obj.datamap['logicalTables'])
#print(obj.get_logical_table('logicalTables'))
What I'm trying to do is if I call get_logical_table I should be able to get region_table_one and region_table_two.
is there any way that if I pass get_logical_table output to get the logicalColumns inside that JSON object.
I'm referencing:
- https://thepythonguru.com/reading-and-writing-json-in-python/
- Deserialize a json string to an object in python
To some extent, but stuck with reading notes to a class. Thanks for the help in advance.
Update:
import json
class DataMap(object):
def __init__(self):
self.logical_tables = None
with open('datamap.json') as f:
self.__dict__ = json.load(f)
self.data_map = self.__dict__['datamap']
def get_map_id(self):
return self.data_map['mapId']
def get_version(self):
return self.data_map['version']
def get_region(self):
return self.data_map['region']
def get_source_provider(self):
return self.data_map['sourceProvider']
def __getitem__(self, key):
return self.data_map[key]
def __repr__(self):
return repr(self.data_map)
def __len__(self):
return len(self.__dict__['datamap'])
def copy(self):
return self.data_map.copy()
def has_key(self, k):
return k in self.data_map
def keys(self):
return self.data_map.keys()
def values(self):
return self.data_map.values()
def items(self):
return self.data_map.items()
def pop(self, *args):
return self.data_map.pop(*args)
def __contains__(self, item):
return item in self.data_map
def __iter__(self):
return iter(self.data_map)
class LogicalTables(DataMap):
def __init__(self):
DataMap.__init__(self)
self.logical_tables = self.data_map['logicalTables']
logical_table = None
for table in self.get_all_logical_tables():
self.name = table.get("name")
print(self.name)
def __len__(self):
return len(self.data_map['logicalTables'])
def __repr__(self):
return repr(self.logical_tables)
def createName(self):
self.name = "Temporary Value"
def has_key(self, k, table_name=None):
"""Check if the dict has given key"""
logical_table = self.get_logical_table(table_name)
return k in logical_table
def get_all_logical_tables(self, tableName=None):
return self.data_map['logicalTables']
def get_logical_table(self, table_name=None):
logical_table = None
for table in self.get_all_logical_tables():
if table.get("name") == table_name:
logical_table = table
return logical_table
def get_logical_table_list(self, table_name=None):
table_list = []
for table in self.get_all_logical_tables():
table_list.append(table.get("name"))
return table_list
class LogicalColumns(LogicalTables):
def __init__(self):
LogicalTables.__init__(self)
self.logical_columns = self.logical_tables['logicalColumns']
def __len__(self):
return len(self.logical_columns['logicalColumns'])
def __repr__(self):
return repr(self.logical_columns)
I have updated and this is my current class.
logicalTables in your json input is actually a list, not a dict, so you doing ['logicalTables']['name'] won't work.
You need to change get_logical_table to something like this:
def get_logical_table(self, tableName):
for table in self.datamap['logicalTables']:
if table['name'] == tableName:
return table['logicalColumns']
Instead of iterating through lists, it would be better to transform your dict so you could directly access any logicalTable with its name (if they are unique).
Update:
You can transform the dict like so:
tables = {}
for table in self.datamap['logicalTables']:
name = table['name']
del table['name']
tables[name] = table
self.datamap['logicalTables'] = tables
# Use like so:
table_one = self.datamap['logicalTables']['region_table_one']
As title, A json object or convert to a python object like:
u = {
"name": "john",
"coat": {
"color": "red",
"sex": "man",
},
"groups": [
{"name": "git"},
{"name": "flask"}
]
}
I want visit as:
u.name
It's easy to do with inherit from dict, but
u.groups.0.name
We also set it as
u.name = "flask"
u.groups.0.name = "svn"
Thanks
Python is not JavaScript. You need to refer to u["groups"][0]["name"].
May be it's difficult, because integer as key is invalid.
I do like this
class Dict(dict):
def __init__(self, value):
if isinstance(value, (list, tuple)):
value = dict(zip(['_%s' % i for i in range(len(value))], value))
super(Dict, self).__init__(value)
def __getattr__(self, key):
try:
if type(self.__getitem__(key)) in (dict, OrderedDict, tuple, list):
return Dict(self.__getitem__(key))
return self.__getitem__(key)
except KeyError:
raise AttributeError(key)
def __setattr__(self, key, value):
try:
return self.__setitem__(key, value)
except KeyError:
raise AttributeError(key)
u = {
"name": "john",
"coat": {
"color": "red",
"sex": "man",
},
"groups": [
{"name": "git"},
{"name": "flask"}
]
}
>>> u = Dict(u)
>>> u.name
output: john
>>> u.groups._0
output: {"name": "git"}