docs: def process_flattened(flattened):
      """
      Replace numbers in JSON paths (representing positions in arrays) with special objects. This ensures that objects
      in arrays with different `id` values have different JSON paths – and makes it easy to identify such arrays.
      """
      # Keep arrays in order.
      processed = OrderedDict()
  
      # Cache identifiers, to avoid minting a new ID for each field of the same object.
      identifiers = {}
  
      for key in flattened:
          new_key = []
          for end, part in enumerate(key, 1):
              # If this is a path to an item in an array.
              if isinstance(part, int):
                  if key[:end] in identifiers:
                      part = identifiers[key[:end]]
                  else:
                      # If it is an array of objects, get the `id` value to apply the identifier merge strategy.
                      # http://standard.open-contracting.org/latest/en/schema/merging/#identifier-merge
                      id_value = flattened.get(key[:end] + ('id',))
  
                      # If the object contained no top-level `id` value, set a unique value.
                      if id_value is None:
                          identifier = uuid.uuid4()
                      else:
                          identifier = id_value
  
                      # Save the original value. (If the value is an integer, this avoids coercing it to a string.)
                      part = IdValue(identifier)
                      part.original_value = id_value
  
                      identifiers[key[:end]] = part
              new_key.append(part)
          processed[tuple(new_key)] = flattened[key]
  
      return processed