Handling Dynamic Mapping Property that can be json object or string

Versions (relevant - OpenSearch/Dashboard/Server OS/Browser):
AWS OpenSearch_2.13

Describe the issue:
Is there any way to handle a mapping property to be an object or just a string?
So right now, we have dynamic mapping of property “domain”, the data inserted is uncontrolled and could be a JSON Object or just a string (simplest example i can give)

I know the flow is wrong, but im new to opensearch and there might be explicit mapping or other work around. we cannot save the JSON Object as string under domain cause we can do query on it like: domain.exception.property_1 etc

so current the flow is:
1. insert a first data like this. in this case, “domain” will be registered an object due to dynamic mapping.

PUT /test-events/_doc/1
{
  "domain": {
    "exception": {
        "error_code": 400,
        "error_message": "Invalid Request"
     }
  }
}

2. then insert second document. in this case, mapper_parsing_exception will be throw as we are sending a string to the “domain.exception” property, in which object has been registered in the mapping

PUT /test-events/_doc/2
{
  "domain": {
    "exception": "400 error - invalid request"
  }
}

Configuration:
Dynamic Mapping of properties

Relevant Logs or Screenshots:

{
  "error": {
    "root_cause": [
      {
        "type": "mapper_parsing_exception",
        "reason": "object mapping for [domain.exception] tried to parse field [exception] as object, but found a concrete value"
      }
    ],
    "type": "mapper_parsing_exception",
    "reason": "object mapping for [domain.exception] tried to parse field [exception] as object, but found a concrete value"
  },
  "status": 400
}

Maybe you can try to parse the string type exception to a json object by ingest pipeline, after that you will have an uniform way to index all documents no matter the original field is object or string, something like this:

POST _ingest/pipeline/_simulate
{
  "pipeline": {
    "processors": [
      {
        "dissect": {
          "field": "domain.exception",
          "pattern": "%{error_code} %{error_message}",
          "if": "ctx.domain.exception instanceof String"
        }
      },
      {
        "remove": {
          "field": [
            "domain.exception"
          ],
          "if": "ctx.domain.exception instanceof String"
        }
      },
      {
        "copy": {
          "source_field": "error_code",
          "target_field": "domain.exception.error_code",
          "remove_source": true,
          "ignore_missing":true
        }
      },
      {
        "copy": {
          "source_field": "error_message",
          "target_field": "domain.exception.error_message",
          "remove_source": true,
          "ignore_missing":true
        }
      }
    ]
  },
  "docs": [
    {
      "_source": {
        "domain": {
          "exception": "400 error - invalid request"
        }
      }
    },
    {
      "_source": {
        "domain": {
          "exception": {
            "error_code": 400,
            "error_message": "Invalid Request"
          }
        }
      }
    }
  ]
}

, check the documentation of ingest pipeline for more details: Create pipeline - OpenSearch Documentation.

By the way, you can create an index template to set the field domain.exception to an object field explicitly.