Yebach
Yebach

Reputation: 1691

python parse Json for all null values

Using python on web2py server I have following problem. How do I loop trough json to find all the keys that have null values (or empty strings) and collect those keys to report what is missing:

This is my json example.

 {
"version" : 1,
"general" : {
    "scriptFrom" : "",
    "scriptTo" : "1.1.2014",
    "scriptComment" : "dada"
},
"nbworkersDays" : [{
        "days" : ["1", "2"],
        "data" : [{
                "nbWorkersFrom" : 2,
                "nbWorkersTo" : null,
                "timeFrom" : "12:00",
                "timeTo" : ""
            }
        ,{
            "nbWorkersFrom" : 2,
            "nbWorkersTo" : 7,
            "timeFrom" : "9:00",
            "timeTo" : "14:00"
        }
    ]
    }
]}

I was thinking to retrieve a list with all keys and if nested than first level . second level. missingData= [scriptFrom, nbworkersDays.nbWorkersTo, nbworkersDays.timeTo]

any suggestions on how to solve this or how would you collect all the errors to report back to client (I have a web app using web2py) thank you

Upvotes: 0

Views: 1437

Answers (1)

Reut Sharabani
Reut Sharabani

Reputation: 31339

You can use a recursive function to iterate over the values of complex objects while remembering the path you're at (to report back):

#!/usr/bin/env python

# used to parse the json text
import json
with open('json.txt', 'r') as f:
    d = json.load(f)
# define list of what your consider as "missing"
missings = [None, ""]

# recursive function to collect missing paths and alter the aggregator list
# make sure to add cases if needed
def aggregate_missing_paths(aggregator, path, item):
    if isinstance(item, list):
        # check all list items
        map(lambda x: aggregate_missing_paths(aggregator, path, x), item)
    if isinstance(item, dict):
        # check all dict items
        map(lambda kv: aggregate_missing_paths(aggregator, path + '.' + kv[0], kv[1]), item.iteritems())
    if item in missings:
        # alter list to cotain path to missing
        aggregator.append(path)

aggregator = []
aggregate_missing_paths(aggregator, 'root', d)
print aggregator

Edit:

I added a version without the aggregator using a recursive generator:

#!/usr/bin/env python

import json
with open('json.txt', 'r') as f:
    d = json.load(f)
missings = [None, ""]
def generate_missing_paths(path, item):
    if isinstance(item, list):
        for v in item:
            for current_path in generate_missing_paths(path, v):
                yield current_path
    if isinstance(item, dict):
        for k, v in item.iteritems():
            for current_path in generate_missing_paths(path + '.' + k, v):
                yield current_path
    if item in missings:
        yield path

for path in generate_missing_paths('root', d):
    print path

Upvotes: 2

Related Questions