2014-09-01 5 views
0

Так что я работаю с API, который возвращает JSON после отправки запроса на него. Я написал класс оболочки вокруг этого ответа JSON, чтобы я мог обрабатывать любые изменения в JSON в одном месте. Это также помогает мне легко получить доступ к ценностям.Обработка разного ответа json

Вот обертка я писал:

class WitResponse: 
    def __init__(self, json_string): 
     self.json_string = json_string 
     self.wit_response = json.loads(json_string) 

    @property 
    def intent(self): 
     return self.wit_response["outcomes"][0]["intent"] 

    @property 
    def confidence(self): 
     return self.wit_response["outcomes"][0]["confidence"] 

    @property 
    def text(self): 
     return self.wit_response["_text"] 

    @property 
    def entites(self): 
     return self.wit_response["outcomes"][0]["entites"] 

    @property 
    def msg_id(self): 
     return self.wit_response["msg_id"] 

    @property 
    def response(self): 
     return self.json_string.translate(None,"\n")+"\n" #Saves the reply in an already easy to send format 

    @property 
    def target(self): 
     return self.wit_response["outcomes"][0]["entities"]["target"][0]["value"] 

Пример очень частом ключ, который можно найти в формате JSON является target ключ (как это можно увидеть выше). Поскольку он не всегда существует, вызов метода target вызовет исключение. Я ищу решение для обработки таких полей, которые будут настолько элегантными, насколько это возможно.

На данный момент я просто завернул заявление о возвращении в методе target с попыткой, за исключением блока и возвращает None если возбуждается исключение (JSON не имеет target ключа).

Я также рассматривал возможность использования декоратора, который добавляет попробовать, за исключением блока, однако это не похоже на работу, когда я добавил декоратор над @property декоратора:

def None_Return_Value_Decorator(func): 
    def wrapper(self): 
     try: 
      value = func(self) 
      return value 
     except: 
      return None 

    return wrapper 

Существуют ли более элегантные решения ? Если нет, может ли один декоратор работать (и как его исправить, если это так)?

ответ

2

Добавить ваш декоратор ниже в @property декоратора:

@property 
@None_Return_Value_Decorator 
def target(self): 
    return self.wit_response["outcomes"][0]["entities"]["target"][0]["value"] 

Теперь ваш декоратор применяется первым, перед включением возвращаемого значения вашего декоратора в собственности добытчик.

Вы хотите avoid using a except handler однако; попытайтесь найти только соответствующее исключение, например IndexError и KeyError.

Вы можете сделать исключения конфигурируемый в декоратора:

from functools import wraps 

def ignore_exception(*exceptions): 
    def decorator(f): 
     @wraps(f) 
     def wrapper(*args, **kw): 
      try: 
       return f(*args, **kw) 
      except exceptions: 
       return None 
     return wrapper 
    return decorator 

затем использовать как:

@property 
@ignore_exception(KeyError) 
def target(self): 
    return self.wit_response["outcomes"][0]["entities"]["target"][0]["value"] 

, например.

+0

Это похоже на работу. Знаете ли вы, как лучше справиться с этим, чем у меня уже есть? Это кажется мне очень неуместным. – Shookie

+0

@Shookie: если вы используете Python 3.4, вы можете использовать новый контекст-менеджер контекста [contextlib.suppress()] (https://docs.python.org/3/library/contextlib.html#contextlib.suppress). –

+0

@Shookie: но использование декоратора для инкапсуляции обычной обработки отлично подходит для меня; вы можете заставить декоратора принять исключение (ы), чтобы поймать как аргумент. –

Смежные вопросы