There is an incoming json(data.json) :

 { "data": [ { "Name": "Ivan", "parameter1": "XXX", "parameter2": 0, "parameter3": 0, "date": "2016-07-12T00:00:00", "parameter4": 2 }, { "Name": "Ivan", "parameter1": "YYY", "parameter2": 0, "parameter3": 0, "date": "2016-07-12T00:00:00", "parameter4": 2 }, { "Name": "Oleg", "parameter1": "XXX", "parameter2": 2, "parameter3": 3, "date": "2016-07-12T00:00:00", "parameter4": 2 }, { "Name": "Oleg", "parameter1": "YYY", "parameter2": 4, "parameter3": 3, "date": "2016-07-12T00:00:00", "parameter4": 2 } ] } 

The task is to parse this json(attachments.json) , substitute the values ​​into another json for the Slack messenger, then send it with a message of the following type:

 [ { "fallback": "Required plain-text summary of the attachment.", "color": "good", "pretext": "мяу" }, { "author_name": "Ivan", "author_icon": "http://unicodey.com/emoji-data/img-twitter-64/1f4e2.png", "fields": [ { "title": "parameter1", "value": "XXX", "short": "true" }, { "title": "parameter2", "value": "0", "short": "true" }, { "title": "parameter3", "value": "0", "short": "true" }, { "title": "parameter4", "value": "2", "short": "true" }, { "title": "parameter1", "value": "YYY", "short": "true" }, { "title": "parameter2", "value": "0", "short": "true" }, { "title": "parameter3", "value": "0", "short": "true" }, { "title": "parameter4", "value": "2", "short": "true" }, ] }, { "author_name": "Oleg", "author_icon": "http://unicodey.com/emoji-data/img-twitter-64/1f4e2.png", "fields": [ { "title": "parameter1", "value": "XXX", "short": "true" }, { "title": "parameter2", "value": "0", "short": "true" }, { "title": "parameter3", "value": "0", "short": "true" }, { "title": "parameter4", "value": "2", "short": "true" }, { "title": "parameter1", "value": "YYY", "short": "true" }, { "title": "parameter2", "value": "0", "short": "true" }, { "title": "parameter3", "value": "0", "short": "true" }, { "title": "parameter4", "value": "2", "short": "true" }, ] }, 

My current solution is:

  • create a dictionary

     Ivan = dict(xxx={'s': 0, 'c': 0, 'a': 0,}, yyy={'s': 0, 'c': 0, 'a': 0,}) 
  • Parse the first json function and write the necessary values ​​to the dictionary

     def get_data(): with open('data.json', 'r') as data: jsonsheet = json.load(data) jsondata = jsonsheet["data"] for i in jsondata: if i['parameter1'] == 'XXX': if i['Name'] == 'Ivan': Ivan['xxx']['s'] = i['parameter2'] Ivan['xxx']['c'] = i['parameter3'] Ivan['xxx']['a'] = i['parameter4'] elif i['parameter2'] == 'YYY': Ivan['yyy']['s'] = i['parameter2'] Ivan['yyy']['c'] = i['parameter3'] Ivan['yyy']['a'] = i['parameter4'] 
  • the function loads json(attachments.json) takes the necessary values ​​from the dictionary ( Ivan ) and overwrites the data and returns json .

     def load_data(): with open('attachments.json', 'r', encoding='utf-8') as msg: msgdata = json.load(msg) jsonmsg = msgdata[1] jsonmsg['fields'][2]['value'] = Ivan['parameter2']['s'] return json.dumps(msgdata, ensure_ascii=False) 

Questions:

  1. If I call print(load_data()) , it will return json with modified values, however, when I send a message to the chat, then an unchanged json is given. Why is that?

  2. In the incoming json there may be other names besides Ivan with the same parameters. I suppose that it is possible to create a class for such a case, but I don’t understand how to bind it to the get_data() function?

  3. Is there a more elegant solution instead of get_data() ?

  4. The code seems extremely large. Maybe someone has ideas on refactoring?

Addition: Instead of a dictionary I decided to use a class

 class Salesmanager: def __init__(self, n): self.name = n self.xxx = ['xxx',{'sum': 0, 'chq': 0, 'avg': 0}] self.yyy = ['yyy',{'sum': 0, 'chq': 0, 'avg': 0}] def setname(self, newname): self.name = newname def set_values_d(self, s, c, a): self.xxx[1]['sum'] = s self.xxx[1]['chq'] = c self.xxx[1]['avg'] = a def set_values_nd(self, s, c, a): self.yyy[1]['sum'] = s self.yyy[1]['chq'] = c self.yyy[1]['avg'] = a def __str__(self): return 'Имя: {0}\n''xxx: {1}\n''yyy: {2}'. \ format(self.name, self.xxx, self.yyy) 

    1 answer 1

    If you understand the problem correctly, here is:

     import json from datetime import datetime input_json = """{ "data": [ { "Name": "Ivan", "parameter1": "XXX", "parameter2": 0, "parameter3": 0, "date": "2016-07-12T00:00:00", "parameter4": 2 }, { "Name": "Ivan", "parameter1": "YYY", "parameter2": 0, "parameter3": 0, "date": "2016-07-12T00:00:09", "parameter4": 2 } ] }""" def get_data(json_string): # я использую loads(-tring) по тому что у меня строка, если вы принимаете # .json используйте load json_string = json.loads(json_string) # словарь это не сортированный массив данных, и если порядок важен, то # его нужно отсортировать, и сделаем мы это по полю дата. # я не знаю в каком формате тут дата гггг-мм-дд или гггг-дд-мм # точно также как и не знаю часы в 12 или 24 формате (хотя скорее всего 24). # в случае если будут ощибки то маску можешь собрать сам # по этой таблице: # https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior json_string['data'] = sorted(json_string['data'], key=lambda x: datetime.strptime(x['date'], '%Y-%m-%dT%H:%M:%S')) output_json = { "author_name": "Ivan", "author_icon": "link_to_img", "fields": list() } for msg in json_string['data']: # ну я так понимаю дату ты не передаешь, так что она нам не нужна, # как и имя. del msg['date'], msg['Name'] for parameter, value in msg.items(): output_json['fields'].append({ "title": parameter, "value": value, "short": True }) return json.dumps(output_json) print(get_data(input_json)) 

    This is of course not the final version but the implementation of this block:

     { "author_name": "Ivan", "author_icon": "link_to_img", "fields": [ { "title": "parameter1", "value": "XXX", "short": "true" } ] } 

    If I do not quite understand the task, sign off, I will correct the implementation.

    • json i get by url. Work with files was done for convenience (so as not to make requests every 2 minutes). Next, the data I need to substitute in the right places attachments.json and send to chat. I corrected my question (added class). - DmitryC
    • Although I do not see the class. And I do not understand why it is necessary. Shoot a bazooka at unicellular, my dear. - Vasiliy Rusin
    • The class has not added yet. There, in order to understand everything, you need to rewrite the function, but it is not ready yet. Why the class: in the incoming json there will be Ivana, Petit, Zina (only 3). In order not to write them all into the dictionary every time, I thought that you could create a class object based on the incoming json data, and then take values ​​for outgoing json from this class. It is not right? - DmitryC
    • So you have a name in json'e, why would you write them in a dictionary? Take the name from the incoming json'a and all. As I said, the function that I wrote almost completely returns the ready json that you asked for, except for the parameters that you did not tell where it came from. - Vasiliy Rusin
    • Write here the input and output json'y with two people. codeshare.io/893d8 - Vasiliy Rusin