3
\$\begingroup\$

I made a function that turns all child from a JSON file to parents (or brothers?). It adds the parent name to the key, so there are no duplicates.

It works ok, but I would like to ask if there are better ways to do this, in a logic, pythonic and even syntaxic way. I feel I am stuck with if-else logic.

Thank you!

I have this JSON file:

{
   "update_id":1,
   "message":{
      "message_id":1,
      "from":{
         "id":1,
         "is_bot":false,
         "first_name":"Albert",
         "language_code":"es"
      },
      "chat":{
         "id":1,
         "first_name":"Albert",
         "type":"private"
      },
      "date":1,
      "text":"HI"
   }
}

Filtering and convertion from child to parents is done this code:

MF_FIELDS = (
    "message_from_id",
    "message_from_is_bot",
    "message_from_first_name",
    "message_from_username",
    "message_chat_id",
    "message_chat_title",
    "message_chat_type",
    "message_date",
    "message_text",
    "message_entities_type"
)

def dict_to_first_level(d, parent_name=None, rec_dict=None):
    ret_dict = {}

    if rec_dict: ret_dict = {**ret_dict, **rec_dict} 

    for k, v in d.items():

        if isinstance(v, dict):
            if parent_name: k = f'{parent_name}_{k}'

            _recursive = dict_to_first_level(v, k, ret_dict)
            ret_dict = {**ret_dict, **_recursive[0]} 

        else:
            if parent_name:
                k = f'{parent_name}_{k}'
            ret_dict[k] = v

    return ret_dict, parent_name, rec_dict

def filter_json(encoded_json, filter):
    ret_dict = {}
    json_dict = json.loads(encoded_json)
    first_level_dict, _, _ = dict_to_first_level(json_dict)

    for k, v in first_level_dict.items():
        if k in filter:
            ret_dict[k] = v
    return ret_dict

Producing this result:

{
   "message_from_id":1,
   "message_from_is_bot":false,
   "message_from_first_name":"Albert",
   "message_chat_id":1,
   "message_chat_type":"private",
   "message_date":1,
   "message_text":"HI"
}
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

The main issues are naming and formatting.

MF_FIELDS - what is mf?
ret_dict - what is ret?
rec_dict - what is rec? it's easy to mix it up with ret_dict
k and v can be key and value
what is _recursive?
filter shadows a built-in name

if rec_dict: ret_dict = {**ret_dict, **rec_dict}
Split this into 2 lines, it's much easier to read this way. In this case there is no reason to add **ret_dict since ret_dict is empty as was stated on the previous line.

for k, v in d.items():
    if isinstance(v, dict):
        if parent_name: k = f'{parent_name}_{k}'

The line (it should be on a new line) k = f'{parent_name}_{k}' looks like it's trying to change the value of one of the keys in d. But in fact it creates a new object for k to reference without changing the dictionary in any way. To make it clear, don't name this new object k.

In general when you write something like

for element in some_collection:
    element = something

your collection never changes, the name element just stops referring to one of its elements and now points to the same object as something.


I'd like to know what task this algorithm is trying to solve? If you want specific values from the dictionary, you can get them like so:

message_from_first_name = your_dict["message"]["from"]["first_name"]
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.