def to_marqo_document(self, marqo_index: SemiStructuredMarqoIndex) -> Dict[str, Any]:
        """
        Convert SemiStructuredVespaDocument object to marqo document structure.

        Args:
            marqo_index: The SemiStructuredMarqoIndex instance containing index configuration

        Returns:
            Dict[str, Any]: A dictionary representing the marqo document format containing:
                - String array fields (handled differently for pre/post 2.16 indexes)
                - Integer and float fields
                - Boolean fields 
                - Document ID
                - Text fields
                - Tensor fields with chunks and embeddings
        """
        marqo_document = {}

        if self.index_supports_partial_updates and self.string_array_fields:
            # self.string_array_fields is a dictionary, Post 2.16 indexes will have string arrays stored as a map of string to list of strings.
            marqo_document.update(self.string_array_fields)
        else: # Pre 2.16 indexes will have string arrays stored as a list of strings in the SemiStructuredVespaDocumentsFields object under a field called "string_arrays".
            for string_array in self.fixed_fields.string_arrays:
                string_array_key, string_array_value = string_array.split("::", 1) # String_array_key will be string in this case, and string_array_value will be a single string in this case.
                if string_array_key not in marqo_document:
                    marqo_document[string_array_key] = []
                marqo_document[string_array_key].append(string_array_value)

        # Add int and float fields back
        # Please note that int-map and float-map fields are flattened in the result. The correct behaviour is to convert
        # them back to the format when they are indexed. We will keep the behaviour as is to avoid breaking changes.
        marqo_document.update(self.fixed_fields.int_fields)
        marqo_document.update(self.fixed_fields.float_fields)

        marqo_document.update({k: bool(v) for k, v in self.fixed_fields.bool_fields.items()})
        marqo_document[index_constants.MARQO_DOC_ID] = self.fixed_fields.marqo__id
        # Note: We are not adding field_types & version_uuid to the document because
        # it's a field for internal Marqo use only.

        # text fields
        for field_name, field_content in self.text_fields.items():
            marqo_document[field_name] = field_content

        # tensor fields
        for field_name, field_content in self.tensor_fields.items():
            tensor_field = marqo_index.tensor_subfield_map[field_name]

            if constants.MARQO_DOC_TENSORS not in marqo_document:
                marqo_document[constants.MARQO_DOC_TENSORS] = dict()
            if tensor_field.name not in marqo_document[constants.MARQO_DOC_TENSORS]:
                marqo_document[constants.MARQO_DOC_TENSORS][tensor_field.name] = dict()

            if field_name == tensor_field.chunk_field_name:
                marqo_document[constants.MARQO_DOC_TENSORS][tensor_field.name][constants.MARQO_DOC_CHUNKS] = field_content
            elif field_name == tensor_field.embeddings_field_name:
                try:
                    marqo_document[constants.MARQO_DOC_TENSORS][tensor_field.name][
                        constants.MARQO_DOC_EMBEDDINGS] = list(field_content['blocks'].values())
                except (KeyError, AttributeError, TypeError) as e:
                    raise VespaDocumentParsingError(
                        f'Cannot parse embeddings field {field_name} with value {field_content}'
                    ) from e

        if self.fixed_fields.vespa_multimodal_params:
            marqo_document[common.MARQO_DOC_MULTIMODAL_PARAMS] = dict()
            for multimodal_field_name, serialized_multimodal_params in self.fixed_fields.vespa_multimodal_params.items():
                marqo_document[common.MARQO_DOC_MULTIMODAL_PARAMS][multimodal_field_name] = \
                    json.loads(serialized_multimodal_params)

        # Hybrid search raw scores
        if self.fixed_fields.raw_tensor_score is not None:
            marqo_document[index_constants.MARQO_DOC_HYBRID_TENSOR_SCORE] = self.fixed_fields.raw_tensor_score
        if self.fixed_fields.raw_lexical_score is not None:
            marqo_document[index_constants.MARQO_DOC_HYBRID_LEXICAL_SCORE] = self.fixed_fields.raw_lexical_score

        return marqo_document

        Convert SemiStructuredVespaDocument object to marqo document structure.

        Args:
            marqo_index: The SemiStructuredMarqoIndex instance containing index configuration

        Returns:
            Dict[str, Any]: A dictionary representing the marqo document format containing:
                - String array fields (handled differently for pre/post 2.16 indexes)
                - Integer and float fields
                - Boolean fields 
                - Document ID
                - Text fields
                - Tensor fields with chunks and embeddings
        
src/marqo/core/semi_structured_vespa_index/semi_structured_document.py