code: def loads_config(s,
                   parser_params=JSONParserParams(),
                   string_to_scalar_converter=DefaultStringToScalarConverter()):
      
      parser = JSONParser(parser_params)
      object_builder_params = ConfigObjectBuilderParams(string_to_scalar_converter=string_to_scalar_converter)
      listener = ObjectBuilderParserListener(object_builder_params)
      parser.parse(s, listener)
      return listener.result
docs: Works similar to the loads() function but this one returns a json object hierarchy
      that wraps all json objects, arrays and scalars to provide a nice config query syntax.
      For example:
      my_config = loads_config(json_string)
      ip_address = my_config.servers.reverse_proxy.ip_address()
      port = my_config.servers.reverse_proxy.port(80)
  
      Note that the raw unwrapped values can be fetched with the __call__ operator.
      This operator has the following signature: __call__(default=None, mapper=None).
      Fetching a value without specifying a default value means that the value is required
      and it has to be in the config. If it isn't there then a JSONConfigValueNotFoundError
      is raised. The optional mapper parameter can be a function that receives the unwrapped
      value and it can return something that may be based on the input parameter. You can
      also use this mapper parameter to pass a function that performs checking on the
      value and raises an exception (eg. ValueError) on error.
  
      If you specify a default value and the required config value is not present then
      default is returned. In this case mapper isn't called with the default value.