@@ -20,17 +20,20 @@ def _merge_options(self, options):
2020 self ._options = options
2121
2222 assert self ._options .get ("separator" , "dot" ) in [
23- "dot" , "bracket" , "mixed" ]
23+ "dot" , "bracket" , "mixed" , "mixed-dot" ]
2424 assert isinstance (self ._options .get ("raise_duplicate" , False ), bool )
2525 assert isinstance (self ._options .get ("assign_duplicate" , False ), bool )
2626
2727 self .__is_dot = False
2828 self .__is_mixed = False
2929 self .__is_bracket = False
30+ self .__is_mixed_dot = False
3031 if self ._options ["separator" ] == "dot" :
3132 self .__is_dot = True
3233 elif self ._options ["separator" ] == "mixed" :
3334 self .__is_mixed = True
35+ elif self ._options ["separator" ] == "mixed-dot" :
36+ self .__is_mixed_dot = True
3437 else :
3538 self .__is_bracket = True
3639 self ._reg = re .compile (r"\[|\]" )
@@ -54,13 +57,9 @@ def span(key, i):
5457 key = key [idx :]
5558
5659 i = 0
60+ last_is_list = False
5761 while i < len (key ):
58- if key [i ] == '.' :
59- i += 1
60- idx = span (key , i )
61- keys .append (key [i : idx ])
62- i = idx
63- elif key [i ] == '[' :
62+ if key [i ] == '[' :
6463 i += 1
6564 idx = span (key , i )
6665 if key [idx ] != ']' :
@@ -72,9 +71,22 @@ def span(key, i):
7271 f"invalid format key '{ full_keys } ', list key is not a valid number at position { i + pos } " )
7372 keys .append (int (key [i : idx ]))
7473 i = idx + 1
74+ last_is_list = True
7575 elif key [i ] == ']' :
7676 raise ValueError (
7777 f"invalid format key '{ full_keys } ', not start with bracket at position { i + pos } " )
78+ elif (key [i ] == '.' and self .__is_mixed_dot ) or (
79+ not self .__is_mixed_dot and (
80+ (key [i ] != '.' and last_is_list ) or
81+ (key [i ] == '.' and not last_is_list )
82+ )
83+ ):
84+ if self .__is_mixed_dot or not last_is_list :
85+ i += 1
86+ idx = span (key , i )
87+ keys .append (key [i : idx ])
88+ i = idx
89+ last_is_list = False
7890 else :
7991 raise ValueError (
8092 f"invalid format key '{ full_keys } ', invalid char at position { i + pos } " )
@@ -90,7 +102,7 @@ def split_key(self, key):
90102 # reduce + filter are a hight cost so do manualy with for loop
91103
92104 # optimize by split with string func
93- if self .__is_mixed :
105+ if self .__is_mixed or self . __is_mixed_dot :
94106 return self .mixed_split (key )
95107 if self .__is_dot :
96108 length = 1
@@ -133,7 +145,7 @@ def set_type(self, dtc, key, value, full_keys, prev=None, last=False):
133145 return key
134146
135147 def get_next_type (self , key ):
136- if self .__is_mixed :
148+ if self .__is_mixed or self . __is_mixed_dot :
137149 return [] if isinstance (key , int ) else {}
138150 return [] if key .isdigit () else {}
139151
0 commit comments