использовать Python рекурсивную функцию для анализа JSON с некоторыми правилами - PullRequest
0 голосов
/ 26 марта 2019

Используйте Python для анализа json по его операции

это мой intput JSON

injson = {
    "$op": "gte",
    "$params": [
        {
            "$op": "startswith",
            "$params": ["yang", "y"]
        },
        {
            "$op": "type",
            "$params": ["yang", "string"]
        }
    ]
}

я хочу получить, но хочу реализовать с помощью функции

out = "yang".startswith("y") >= isinstance("yang", str)
print(out)

"начинается с", "тип", "gte" возвращают логическое значение

$ op - это то, что нужно сделать, $ params - это параметры со списком, может быть много слоев, я хочу написать рекурсивную функцию для ее реализации с использованием python

1 Ответ

1 голос
/ 26 марта 2019

Я интерпретирую этот вопрос как «моя injson структура данных содержит серию объектов, которые представляют компоненты выражения. Как я могу оценить это выражение и вернуть окончательный результат?»

Грамматика вашего языка выражений выглядит довольно просто: каждый компонент представляет собой либо простое значение, такое как «yang», либо словарь, представляющий вызов функции. Таким образом, ваш рекурсивный оценщик должен обрабатывать только эти два случая. Большая часть реальной работы будет заключаться в переводе ваших пользовательских операторов в нечто, понятное Python.

Пример реализации:

import operator

def check_type(obj, type_name):
    #we can't just directly use `isinstance` for type checks, because `isinstance("foo", "string")` doesn't understand what the second argument is supposed to represent.
    #so we need an extra layer here to convert type-looking strings into actual types.
    types_by_name = {"string": str, "int": int, "bool": bool} #add more types as desired
    return isinstance(obj, types_by_name[type_name])

operators_by_name = {
    "gte": operator.ge,
    "startswith": str.startswith,
    "type": check_type,
    #add more named functions as desired
}

def eval_json(obj):
    if isinstance(obj, dict) and "$op" in obj:
        op = operators_by_name[obj["$op"]]
        args = [eval_json(arg) for arg in obj["$params"]]
        return op(*args)
    else:
        return obj

injson = {
    "$op": "gte",
    "$params": [
        {
            "$op": "startswith",
            "$params": ["yang", "y"]
        },
        {
            "$op": "type",
            "$params": ["yang", "string"]
        }
    ]
}
print(eval_json(injson))

Результат:

True

Это желаемый результат, поскольку "yang".startswith("y") >= isinstance("yang", str) также имеет значение True.

...