docs: def json2value(json_string, params=Null, flexible=False, leaves=False):
      """
      :param json_string: THE JSON
      :param params: STANDARD JSON PARAMS
      :param flexible: REMOVE COMMENTS
      :param leaves: ASSUME JSON KEYS ARE DOT-DELIMITED
      :return: Python value
      """
      if not is_text(json_string):
          Log.error("only unicode json accepted")
  
      try:
          if flexible:
              # REMOVE """COMMENTS""", # COMMENTS, //COMMENTS, AND \n \r
              # DERIVED FROM https://github.com/jeads/datasource/blob/master/datasource/bases/BaseHub.py# L58
              json_string = re.sub(r"\"\"\".*?\"\"\"", r"\n", json_string, flags=re.MULTILINE)
              json_string = "\n".join(remove_line_comment(l) for l in json_string.split("\n"))
              # ALLOW DICTIONARY'S NAME:VALUE LIST TO END WITH COMMA
              json_string = re.sub(r",\s*\}", r"}", json_string)
              # ALLOW LISTS TO END WITH COMMA
              json_string = re.sub(r",\s*\]", r"]", json_string)
  
          if params:
              # LOOKUP REFERENCES
              json_string = expand_template(json_string, params)
  
          try:
              value = wrap(json_decoder(text_type(json_string)))
          except Exception as e:
              Log.error("can not decode\n{{content}}", content=json_string, cause=e)
  
          if leaves:
              value = wrap_leaves(value)
  
          return value
  
      except Exception as e:
          e = Except.wrap(e)
  
          if not json_string.strip():
              Log.error("JSON string is only whitespace")
  
          c = e
          while "Expecting '" in c.cause and "' delimiter: line" in c.cause:
              c = c.cause
  
          if "Expecting '" in c and "' delimiter: line" in c:
              line_index = int(strings.between(c.message, " line ", " column ")) - 1
              column = int(strings.between(c.message, " column ", " ")) - 1
              line = json_string.split("\n")[line_index].replace("\t", " ")
              if column > 20:
                  sample = "..." + line[column - 20:]
                  pointer = "   " + (" " * 20) + "^"
              else:
                  sample = line
                  pointer = (" " * column) + "^"
  
              if len(sample) > 43:
                  sample = sample[:43] + "..."
  
              Log.error(CAN_NOT_DECODE_JSON + " at:\n\t{{sample}}\n\t{{pointer}}\n", sample=sample, pointer=pointer)
  
          base_str = strings.limit(json_string, 1000).encode('utf8')
          hexx_str = bytes2hex(base_str, " ")
          try:
              char_str = " " + "  ".join((c.decode("latin1") if ord(c) >= 32 else ".") for c in base_str)
          except Exception:
              char_str = " "
          Log.error(CAN_NOT_DECODE_JSON + ":\n{{char_str}}\n{{hexx_str}}\n", char_str=char_str, hexx_str=hexx_str, cause=e)