Home > Blockchain >  Switching From Lists to JSON
Switching From Lists to JSON

Time:03-02

I currently have a script that uses a number of lists as lookups which have a structure like so:

people.py

roster = ['Bob','Alice','Trent','Eve','Mallory','Chad','Victor','Grace']

roles.py

ClassA = ['Bob','Alice','Trent','Eve']
ClassB = ['Bob','Mallory','Chad','Victor','Grace']

portraits.py

portrait = {
'bob':'bob.png',
'alice':'alice.png',
'trent':'trent.png',
'eve':'eve.png',
'mallory':'mallory.png',
'chad':'chad.png',
'victor':'victor.png',
'grace':'grace.png'
}

main.py

import people
import roles
import portraits

classes=['ClassA','ClassB']

names = people.roster
for name in names:
    
    n = name.replace("-", "").replace("'", "").replace(".", "").replace(" ", "").lower()
    picture = portraits.portrait[n]

for p in classes:
    rslt = getattr(roles, p)
    #more operations here, e.g. a dataframe filter: df = df[df['name'].isin(rslt)]
                               

I would like to move all of this into a uniform data structure like this as it would be easier to maintain:

persons.json

{
   "title":"person-schema",
   "revdate":"02-21-2022",
   "data":[
      {
         "name":"Bob",
         "uid":"bob",
         "id":"s001",
         "portrait":"bob.png",
         "classes": ["ClassA","ClassB"],
         "attributes":[
            {
             
            }]
      },
      {
         "name":"Alice",
         "uid":"alice",
         "id":"s002",
         "portrait":"alice.png",
         "classes": ["ClassA"],
         "attributes":[
            {
             
            }]
      },
      {
         "name":"Mallory",
         "uid":"mallory",
         "id":"s003",
         "portrait":"mallory.png",
         "classes": ["ClassB"],
         "attributes":[
            {
             
            }]
      }

    ]
}

I know this is a loaded question, but how would I go about rewriting these lookups?

  • people.roster >> ?
  • getattr(roles, p) >> ?
  • portraits.portrait[n] >>?

CodePudding user response:

I would loop through your roster once, doing the necessary matches foreach. For each name, initiate an empty dict, then fill relevant elements.

Something like...

#initiate empty array to hold data
persons_data = []

for name in name:
   person_data = {
      "name": name
      ,"portrait": "{}.png".format(lower(name))  #assumes all persons have photo and standard naming convention
      ,"classes": []
   }

   #assumes standard, unique names across both datasets
   if name in ClassA:
      person_data["classes"].append('ClassA')
   if name in ClassB:
      person_data["classes"].append('ClassB')

   persons_data.append(person_data)


   

CodePudding user response:

Here's a short helper function to quickly json-ify your data:


    from typing import *
    from math import log10, floor
    import portraits, roles, people


    NEXT_ID: Int = 0

    def student_to_json(name: str, attrs: List[Dict[Any, Any]] = [{}])-> Dict[str, Any]:
        name = name.strip().replace("-", "").replace("'", "").replace(".", "").replace(" ", "").lower()
        if name is None or not word.isalpha() or not word.isascii(): return "" # invalid name
        NEXT_ID  = 1
        return {
                "name": name.title(),
                "uid": name,
                "id": f"s{'0' * (3 - floor(log10(NEXT_ID))   1)}{NEXT_ID - 1}"
                "portrait": portraits.portrait.get(name, "blank_avatar.png") # include a default image,
                "classes": [c[1] if name.title in c[0] for c in [(roles.ClassA, "ClassA"), (roles.ClassB, "ClassB")]]
                "attributes": attrs
           }

You could then call this like

   import json
   import datetime
   from datetime import datetime as dt

   # import attributes ??
   # attributes.data[person_name] = [{"eye-color": "blue", ...}, ...]

    with open(f'people-schema.json', 'w ') as fptr:
        data = [student_to_json(p, attributes.data.get(p, [{}])) for p in people.roster]
        json.dumps({"revdate": dt.now(), "data": data}, fptr) # add attributes as necessary

Everything should then be outputted to a new file called people-schema.json.

(Added support for students enrolled in more than one class, per @ScottieB's comment)

CodePudding user response:

The persons.json file exists.

I can bring it in using something like:

 jsonfile = 'persons.json'
 with open(jsonfile) as j:
    data = json.load(j)

For clarification of the ask:

Old method for referencing the list: names = people.roster

New method? names = [x["name"] for x in data.itervalues()] ?

Reference: Get all values from child elements of a dict as a list

  • Related