2015-05-10 7 views
9

Wdrażam "PATCH" po stronie serwera w celu częściowej aktualizacji moich zasobów.Częściowe aktualizacje za pomocą PATCH: jak analizować dane JSON dla aktualizacji SQL?

Zakładając zrobić nie narazić moje SQL schematu bazy danych w JSON żądania/odpowiedzi, a więc istnieje oddzielny mapowanie między kluczy w JSON i kolumn tabeli, w jaki sposób najlepiej która kolumna (e) postać z aktualizacji w języku SQL, biorąc pod uwagę JSON częściowej aktualizacji?

Na przykład, załóżmy, że moja tabela ma 3 kolumny: col_a, col_b i col_c i mapowanie między klawiszami JSON do kolumn tabeli wynosi: a -> col_a, b -> col_b, c -> col_c. Biorąc JSON-PATCH dane:

[ 
    {"op": "replace", "path": "/b", "value": "some_new_value"} 
] 

Jaki jest najlepszy sposób programowo zastosować tę częściową aktualizację do col_b tabeli odpowiadającej moim zasobu?

Oczywiście mogę zakodować te mapowania w A keys_to_columns dict gdzieś, i na każde żądanie z jakimś patch_data mogę zrobić czegoś tak:

mapped_updates = {keys_to_columns[p['path'].split('/')[-1]]: p['value'] for p in patch_data} 

następnie użyć mapped_updates skonstruować instrukcję SQL dla aktualizacji DB. Jeśli powyższe wyrzuci KeyError wiem, że dane żądania są nieprawidłowe i mogą je wyrzucić. I będę musiał to zrobić dla każdego stołu/zasobu jaki mam.

Zastanawiam się, czy istnieje lepszy sposób.

+0

Chyba chcesz tę warstwę abstrakcji, abyś miał możliwość zmiany schematu DB bez wpływu na interfejs API REST? –

+0

@MartinKonecny, tak, również mogę po prostu ukryć semantykę schematu DB z dala od użytkowników API. – MLister

+0

Myślę, że potrzebna jest trzecia warstwa, która znajduje się nad bazą danych, która serializuje i wykonuje zapytania/aktualizacje i reprezentuje dane w żądanej formie na poziomie interfejsu API. np .: [JSON Schema] (http://json-schema.org/), co jest miłe, ponieważ możesz również potwierdzać, dokumentować i utrzymywać zasoby i API elastyczne. –

Odpowiedz

1

Jest to podobne do tego, co planujesz zrobić, ale zamiast tworzyć mapy, możesz utworzyć klasy dla każdego z nich. Na przykład:

class Table(object): 
    """Parent class of all tables""" 

    def get_columns(self, **kwargs): 
     return {getattr(self, k): v for k, v in kwargs.iteritems()} 

class MyTable(Table): 
    """table MyTable""" 

    # columns mapping 
    a = "col_a" 
    b = "col_b" 

tbl = MyTable() 
tbl.get_columns(a="value a", b="value b") 
# the above returns {"col_a": "value a", "col_b": "value b"} 
# similarly: 
tbl.get_columns(**{p['path'].split('/')[-1]: p['value'] for p in patch_data}) 

To jest po prostu coś podstawowego do inspiracji, te zajęcia można rozszerzyć, aby zrobić o wiele więcej.

+0

dziękuję za odpowiedź. Nie szukam konkretnego kodu dla podanego przykładu zabawki (dla którego już przedstawiam rozwiązanie), jestem bardziej zainteresowany najlepszym możliwym podejściem (np. Wzorami projektowymi, bibliotekami itp.) Do problemu. – MLister

+0

Tak i IMHO lepszym rozwiązaniem jest zdefiniowanie klas dla tabel bazy danych podobnych do mojego przykładu, gdzie można zdefiniować odwzorowania pól wyraźnie i pythonowo. Masz także tę zaletę, że rozszerzasz funkcjonalność swoich klas, dodając ogólne metody w klasie/klasach nadrzędnych, które są w razie potrzeby zastępowane. – sirfz

1
patch_json = [ 
    {"op": "replace", "path": "/b", "value": "some_new_value"}, 
    {"op": "replace", "path": "/a", "value": "some_new_value2"} 
] 

def fix_key(item): 
    item['path'] = item['path'].replace('/', 'col_') 
    return item 

print map(fix_key, patch_json) 
+0

dziękuję za odpowiedź.Nie szukam konkretnego kodu dla podanego przykładu zabawki (dla którego już przedstawiam rozwiązanie), jestem bardziej zainteresowany najlepszym możliwym podejściem (np. Wzorami projektowymi, bibliotekami itp.) Do problemu. – MLister

+0

Myślę, że mały problem nie wymaga specjalnego rozwiązania. – Janom

Powiązane problemy