2015-05-10 15 views
9

Tôi đang triển khai 'PATCH' ở phía máy chủ để cập nhật một phần tài nguyên của mình.Cập nhật từng phần qua PATCH: cách phân tích cú pháp dữ liệu JSON cho các bản cập nhật SQL?

Giả sử tôi làm không để lộ lược đồ cơ sở dữ liệu SQL của tôi trong các yêu cầu/phản hồi JSON, tức là có một ánh xạ riêng biệt giữa các khóa trong JSON và cột của bảng, làm cách nào để tìm hiểu xem cột nào cần cập nhật trong SQL cho JSON của một bản cập nhật một phần?

Ví dụ, giả bàn của tôi có 3 cột: col_a, col_b, và col_c, và ánh xạ giữa các phím JSON để cột của bảng là: a -> col_a, b -> col_b, c -> col_c. Với JSON-PATCH dữ liệu: Cách tốt nhất để lập trình áp dụng cập nhật phần này để col_b của bảng tương ứng với tài nguyên của tôi

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

là gì?

Dĩ nhiên tôi có thể hardcode các ánh xạ trong một dict keys_to_columns nơi nào đó, và theo từng yêu cầu với một số patch_data, tôi có thể làm sth như:

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

sau đó sử dụng mapped_updates để xây dựng các câu lệnh SQL cho DB cập nhật. Nếu ở trên ném một số KeyError Tôi biết dữ liệu yêu cầu không hợp lệ và có thể vứt bỏ nó đi. Và tôi sẽ cần phải làm điều này cho mọi bảng/tài nguyên mà tôi có.

Tôi tự hỏi nếu có cách nào tốt hơn.

+0

Tôi đoán bạn muốn lớp trừu tượng này để bạn có thể linh hoạt thay đổi lược đồ DB mà không ảnh hưởng đến REST API? –

+0

@MartinKonecny, vâng, ngoài ra, tôi có thể chỉ muốn ẩn ngữ nghĩa của lược đồ DB khỏi người dùng API. – MLister

+0

Tôi nghĩ rằng những gì bạn cần là một lớp thứ 3 nằm trên DB của bạn mà serializers và thực hiện truy vấn/cập nhật của bạn và đại diện cho các dữ liệu ở dạng bạn muốn ở cấp API. ví dụ: [Lược đồ JSON] (http://json-schema.org/) rất hay vì bạn cũng có thể xác thực, tài liệu và giữ tài nguyên và API linh hoạt. –

Trả lời

1

Điều này tương tự như những gì bạn đang nghĩ đến, nhưng thay vì tạo bản đồ, bạn có thể tạo các lớp cho mỗi bảng thay thế. Ví dụ:

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}) 

Đây chỉ là điều cơ bản để lấy cảm hứng từ, các lớp này có thể được mở rộng để làm được nhiều hơn nữa.

+0

cảm ơn bạn đã trả lời. Tôi không tìm mã cụ thể cho ví dụ đồ chơi tôi đã cung cấp (mà tôi đã trình bày giải pháp), tôi quan tâm nhiều hơn đến cách tiếp cận tốt nhất có thể (ví dụ: các mẫu thiết kế, thư viện, v.v) cho vấn đề. – MLister

+0

Vâng và IMHO cách tiếp cận tốt hơn là định nghĩa các lớp cho các bảng cơ sở dữ liệu của bạn tương tự như ví dụ của tôi, nơi bạn có thể xác định ánh xạ trường rõ ràng và pythonically. Bạn cũng có lợi thế là mở rộng chức năng của các lớp của bạn bằng cách thêm các phương thức chung trong lớp cha (parent) có thể được ghi đè lên khi cần thiết. – 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

cảm ơn bạn đã trả lời.Tôi không tìm mã cụ thể cho ví dụ đồ chơi tôi đã cung cấp (mà tôi đã trình bày giải pháp), tôi quan tâm nhiều hơn đến cách tiếp cận tốt nhất có thể (ví dụ: các mẫu thiết kế, thư viện, v.v) cho vấn đề. – MLister

+0

Tôi nghĩ, vấn đề lúng túng không đòi hỏi giải pháp đặc biệt. – Janom

Các vấn đề liên quan