From 7152bd095f9789d4edea52b035811150d6450964 Mon Sep 17 00:00:00 2001 From: dalang Date: Sun, 12 Jun 2016 10:58:06 +0800 Subject: [PATCH 1/2] Fix bug that list item in json failed to keep original order and dict item in json failed to save its all items for example, the json I want to save via django form as below: { "FAT": { "TARS": {"application": [True, ""], "group": [True, ""], "server": [True, ""]}, "CMS": {"application": [True, ""], "group": [True, ""], "server": [True, ""]}, "CDPortal": {"application": [True, ""], "group": [True, ""], "server": [True, ""]}, }, "UAT": { "TARS": {"application": [True, ""], "group": [True, ""], "server": [True, ""]}, "CMS": {"application": [True, ""], "group": [True, ""], "server": [True, ""]}, "CDPortal": {"application": [True, ""], "group": [True, ""], "server": [True, ""]}, }, "PROD": { "TARS": {"application": [True, ""], "group": [True, ""], "server": [True, ""]}, "CMS": {"application": [True, ""], "group": [True, ""], "server": [True, ""]}, "CDPortal": {"application": [True, ""], "group": [True, ""], "server": [True, ""]}, }, "TEST": { "TARS": {"application": [True, ""], "group": [True, ""], "server": [True, ""]}, "CMS": {"application": [True, ""], "group": [True, ""], "server": [True, ""]}, "CDPortal": {"application": [True, ""], "group": [True, ""], "server": [True, ""]}, }, } after saved, the json changed as below: { 'FAT': {'CMS': {'group': ['True', '']}}, 'PROD': {'CDPortal': {'group': ['True', '']}}, 'TEST': {'TARS': {'server': ['', 'True']}}, 'UAT': {'CDPortal': {'server': ['', 'True']}} } there are two issues this patch to fix: 1. value of json_obj['UAT']['CDPortal']['server'] should be ['True', ''], not ['', 'True'] # order changed 2. once item in json_obj is a dict, like json['FAT'], it should have 3 items ('TARS', 'CMS', 'CDPortal'), but only one item saved. --- splitjson/widgets.py | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/splitjson/widgets.py b/splitjson/widgets.py index 7237c0e..bcd4376 100644 --- a/splitjson/widgets.py +++ b/splitjson/widgets.py @@ -4,6 +4,7 @@ from django import utils import copy from distutils.version import StrictVersion +from collections import OrderedDict try: import simplejson as json except ImportError: @@ -14,6 +15,24 @@ from django.forms.utils import flatatt +def merge_dicts(src_dict, dst_dict): + for k, v in src_dict.items(): + if k not in dst_dict: + dst_dict[k] = v + else: + if type(v) == type(dst_dict[k]): + if isinstance(v, dict): + merge_dicts(v, dst_dict[k]) + elif isinstance(v, list): + dst_dict[k].extend(v) + else: + dst_dict[k] = v + else: + dst_dict[k] = v + + return dst_dict + + class SplitJSONWidget(forms.Widget): def __init__(self, attrs=None, newline='
\n', sep='__', debug=False): @@ -72,9 +91,11 @@ def _prepare_as_ul(self, l): def _to_pack_up(self, root_node, raw_data): - copy_raw_data = copy.deepcopy(raw_data) result = [] + ordered_keys = sorted(raw_data.keys()) + copy_raw_data = OrderedDict(((k, raw_data[k]) for k in ordered_keys)) + def _to_parse_key(k, v): if k.find(self.separator) != -1: apx, _, nk = k.rpartition(self.separator) @@ -84,6 +105,7 @@ def _to_parse_key(k, v): l = [] obj = {} index = None + l.append(v) if apx != root_node: for key, val in copy_raw_data.items(): head, _, t = key.rpartition(self.separator) @@ -103,7 +125,6 @@ def _to_parse_key(k, v): if obj: for i in obj: l.append(obj[i]) - l.append(v) return _to_parse_key(apx, l) except ValueError: # parse dict @@ -128,7 +149,8 @@ def _to_parse_key(k, v): else: return v - for k, v in raw_data.iteritems(): + for k in ordered_keys: + v = raw_data[k] if k in copy_raw_data: # to transform value from list to string v = v[0] if isinstance(v, list) and len(v) is 1 else v @@ -140,7 +162,7 @@ def _to_parse_key(k, v): try: result.extend(d) except: - result.update(d) + merge_dicts(d, result) return result def value_from_datadict(self, data, files, name): From 10f1e4f4ab101f17eae01f8e612a31c449aca7db Mon Sep 17 00:00:00 2001 From: dalang Date: Sun, 12 Jun 2016 16:35:45 +0800 Subject: [PATCH 2/2] Fix ci failed in python 2.6.9 Since OrderedDict is not a build-in lib in python 2.6.9, last commit can not pass the ci verification. this commit removed the dependency of OrderedDict --- splitjson/widgets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/splitjson/widgets.py b/splitjson/widgets.py index bcd4376..d3ea61d 100644 --- a/splitjson/widgets.py +++ b/splitjson/widgets.py @@ -4,7 +4,6 @@ from django import utils import copy from distutils.version import StrictVersion -from collections import OrderedDict try: import simplejson as json except ImportError: @@ -94,7 +93,7 @@ def _to_pack_up(self, root_node, raw_data): result = [] ordered_keys = sorted(raw_data.keys()) - copy_raw_data = OrderedDict(((k, raw_data[k]) for k in ordered_keys)) + copy_raw_data = copy.deepcopy(raw_data) def _to_parse_key(k, v): if k.find(self.separator) != -1: @@ -107,7 +106,8 @@ def _to_parse_key(k, v): index = None l.append(v) if apx != root_node: - for key, val in copy_raw_data.items(): + for key in [ok for ok in ordered_keys if ok in copy_raw_data]: + val = copy_raw_data[key] head, _, t = key.rpartition(self.separator) _, _, index = head.rpartition(self.separator) if key is k: