docs: def get_json_object_lines(annotation: ResourceAnnotation,
                            properties: Dict[str, Any], field: str,
                            url_params: Dict, request: bool = False,
                            object_property: bool = False) -> List[str]:
      """Generate documentation for the given object annotation.
  
      :param doctor.resource.ResourceAnnotation annotation:
          Annotation object for the associated handler method.
      :param str field: Sphinx field type to use (e.g. '<json').
      :param list url_params: A list of url parameter strings.
      :param bool request: Whether the schema is for the request or not.
      :param bool object_property: If True it indicates this is a property of
          an object that we are documenting.  This is only set to True when
          called recursively when encountering a property that is an object in
          order to document the properties of it.
      :returns: list of strings, one for each line.
      """
      sig_params = annotation.logic._doctor_signature.parameters
      required_lines = []
      lines = []
      default_field = field
      for prop in sorted(properties.keys()):
          annotated_type = properties[prop]
          # If the property is a url parameter override the field to use
          # param so that it's not documented in the json body or query params.
          field = default_field
          if request and prop in url_params:
              field = 'param'
  
          types = get_json_types(annotated_type)
          description = annotated_type.description
          obj_ref = ''
          if issubclass(annotated_type, Object):
              obj_ref = get_object_reference(annotated_type)
          elif (issubclass(annotated_type, Array) and
                  annotated_type.items is not None and
                  not isinstance(annotated_type.items, list) and
                  issubclass(annotated_type.items, Object)):
              # This means the type is an array of objects, so we want to
              # collect the object as a resource we can document later.
              obj_ref = get_object_reference(annotated_type.items)
          elif (issubclass(annotated_type, Array) and
                  isinstance(annotated_type.items, list)):
              # This means the type is array and items is a list of types. Iterate
              # through each type to see if any are objects that we can document.
              for item in annotated_type.items:
                  if issubclass(item, Object):
                      # Note: we are just adding them to the global variable
                      # ALL_RESOURCES when calling the function below and not
                      # using the return value as this special case is handled
                      # below in documenting items of an array.
                      get_object_reference(item)
  
          # Document any enum.
          enum = ''
          if issubclass(annotated_type, Enum):
              enum = ' Must be one of: `{}`'.format(annotated_type.enum)
              if annotated_type.case_insensitive:
                  enum += ' (case-insensitive)'
              enum += '.'
  
          # Document type(s) for an array's items.
          if (issubclass(annotated_type, Array) and
                  annotated_type.items is not None):
              array_description = get_array_items_description(annotated_type)
              # Prevents creating a duplicate object reference link in the docs.
              if obj_ref in array_description:
                  obj_ref = ''
              description += array_description
  
          # Document any default value.
          default = ''
          if (request and prop in sig_params and
                  sig_params[prop].default != Signature.empty):
              default = ' (Defaults to `{}`) '.format(sig_params[prop].default)
  
          field_prop = prop
          # If this is a request param and the property is required
          # add required text and append lines to required_lines.  This
          # will make the required properties appear in alphabetical order
          # before the optional.
          line_template = (
              ':{field} {types} {prop}: {description}{enum}{default}{obj_ref}')
          if request and prop in annotation.params.required:
              description = '**Required**.  ' + description
              required_lines.append(line_template.format(
                  field=field, types=','.join(types), prop=field_prop,
                  description=description, enum=enum, obj_ref=obj_ref,
                  default=default))
          else:
              lines.append(line_template.format(
                  field=field, types=','.join(types), prop=field_prop,
                  description=description, enum=enum, obj_ref=obj_ref,
                  default=default))
  
      return required_lines + lines