diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/GenericResourcePatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/GenericResourcePatcher.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6a897482a63b748930bf68710cbe34a5647767b2
--- /dev/null
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/GenericResourcePatcher.kt
@@ -0,0 +1,61 @@
+package rocks.theodolite.kubernetes.patcher
+
+import com.fasterxml.jackson.annotation.JsonTypeName
+import com.fasterxml.jackson.core.JsonToken
+import com.fasterxml.jackson.databind.node.JsonNodeType
+import io.fabric8.kubernetes.api.model.GenericKubernetesResource
+import io.fabric8.kubernetes.api.model.HasMetadata
+import org.json.JSONString
+
+/**
+ * Patches an arbitrary field in a [GenericKubernetesResource].
+ *
+ * @param path Path as List of Strings and Ints to the field to be patched.
+ */
+class GenericResourcePatcher(val path: List<Any>, val type: Type = Type.STRING) : AbstractStringPatcher() {
+
+    override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata {
+
+        if (resource is GenericKubernetesResource) {
+            val castedValue = when (type) {
+                Type.STRING -> value
+                Type.BOOLEAN -> value.toBoolean()
+                Type.NUMBER -> value.toDouble()
+                Type.INTEGER -> value.toInt()
+            }
+            var current: Any? = resource.additionalProperties
+            for (segment in path.dropLast(1)) {
+                current = if (segment is Int && current is MutableList<*> && current.size > segment) {
+                    current.toTypedArray()[segment]
+                } else if (segment is String && current is Map<*, *>) {
+                    current[segment]
+                } else {
+                    throw IllegalArgumentException("Provided path is invalid")
+                }
+            }
+            val segment = path.lastOrNull()
+            if (segment == null) {
+                throw IllegalArgumentException("Path must not be empty")
+            } else if (segment is Int && current is MutableList<*> && current.size > segment) {
+                (current as MutableList<Any?>)[segment] = castedValue
+            } else if (segment is String && current is Map<*, *>) {
+                (current as MutableMap<String, Any>)[segment] = castedValue
+            } else {
+                throw IllegalArgumentException("Cannot set value for path")
+            }
+        }
+        return resource
+    }
+
+    enum class Type(val value: String) {
+        STRING("string"),
+        BOOLEAN("boolean"),
+        NUMBER("number"),
+        INTEGER("integer");
+
+        companion object {
+            fun from(type: String): Type =
+                values().find { it.value == type } ?: throw IllegalArgumentException("Requested Type does not exist")
+        }
+    }
+}
diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt
index f469eaee39e5e2eb9e5aa0ae2bd8346eabf3006d..238e7caa0ad70ca321f134dd36ffd7d3c16871b4 100644
--- a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt
+++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt
@@ -94,6 +94,12 @@ class PatcherFactory {
                     "VolumesConfigMapPatcher" -> VolumesConfigMapPatcher(
                         volumeName = patcher.properties["volumeName"] ?: throwInvalid(patcher)
                     )
+                    "GenericResourcePatcher" -> GenericResourcePatcher(
+                        path = (patcher.properties["path"] ?: throwInvalid(patcher))
+                            .split("/")
+                            .map { it.toIntOrNull() ?: it },
+                        type = patcher.properties["type"]?.let { GenericResourcePatcher.Type.from(it) } ?: GenericResourcePatcher.Type.STRING
+                    )
                     else -> throw InvalidPatcherConfigurationException("Patcher type ${patcher.type} not found.")
                 }
         }
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/GenericResourcePatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/GenericResourcePatcherTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..236a22bfa8cfb50973536cd4ac0f9fd7db9375b1
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/GenericResourcePatcherTest.kt
@@ -0,0 +1,109 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.fabric8.kubernetes.api.model.GenericKubernetesResource
+import io.fabric8.kubernetes.api.model.HasMetadata
+import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer
+import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.kubernetes.client.KubernetesTestServer
+import io.quarkus.test.kubernetes.client.WithKubernetesTestServer
+
+import org.junit.jupiter.api.Assertions.*
+import org.junit.jupiter.api.Test
+import registerResource
+
+@QuarkusTest
+@WithKubernetesTestServer
+internal class GenericResourcePatcherTest {
+
+    @KubernetesTestServer
+    private lateinit var server: KubernetesServer
+
+    @Test
+    fun testPatchString() {
+        val sourceResource = listOf(createServiceMonitor())
+        val patcher = GenericResourcePatcher(listOf("spec", "endpoints", 0, "interval"))
+        val patchedResource = patcher.patch(sourceResource, "20s")
+        patchedResource.forEach {
+            assertEquals(
+                "20s",
+                ((((it as GenericKubernetesResource)
+                    .additionalProperties["spec"] as Map<String, Any>)
+                        ["endpoints"] as List<Any>)
+                        [0] as Map<String, Any>)
+                        ["interval"])
+        }
+    }
+
+    @Test
+    fun testPatchBoolean() {
+        val sourceResource = listOf(createServiceMonitor())
+        val patcher = GenericResourcePatcher(listOf("spec", "endpoints", 0, "honorTimestamps"), GenericResourcePatcher.Type.BOOLEAN)
+        val patchedResource = patcher.patch(sourceResource, "true")
+        patchedResource.forEach {
+            assertEquals(
+                true,
+                ((((it as GenericKubernetesResource)
+                    .additionalProperties["spec"] as Map<String, Any>)
+                        ["endpoints"] as List<Any>)
+                        [0] as Map<String, Any>)
+                        ["honorTimestamps"])
+        }
+    }
+
+    @Test
+    fun testPatchInteger() {
+        val sourceResource = listOf(createServiceMonitor())
+        val patcher = GenericResourcePatcher(listOf("spec", "labelLimit"), GenericResourcePatcher.Type.INTEGER)
+        val patchedResource = patcher.patch(sourceResource, "11")
+        patchedResource.forEach {
+            assertEquals(
+                11,
+                ((it as GenericKubernetesResource)
+                    .additionalProperties["spec"] as Map<String, Any>)
+                        ["labelLimit"])
+        }
+    }
+
+    @Test
+    fun testPatchNumber() {
+        val sourceResource = listOf(createServiceMonitor())
+        val patcher = GenericResourcePatcher(listOf("spec", "myMadeUpProp"), GenericResourcePatcher.Type.NUMBER)
+        val patchedResource = patcher.patch(sourceResource, "11.2")
+        patchedResource.forEach {
+            assertEquals(
+                11.2,
+                ((it as GenericKubernetesResource)
+                    .additionalProperties["spec"] as Map<String, Any>)
+                        ["labelLimit"])
+        }
+    }
+
+    @Test
+    fun testPatchNumberWithoutDecimals() {
+        val sourceResource = listOf(createServiceMonitor())
+        val patcher = GenericResourcePatcher(listOf("spec", "myMadeUpProp"), GenericResourcePatcher.Type.NUMBER)
+        val patchedResource = patcher.patch(sourceResource, "11")
+        patchedResource.forEach {
+            assertEquals(
+                11.0,
+                ((it as GenericKubernetesResource)
+                    .additionalProperties["spec"] as Map<String, Any>)
+                        ["labelLimit"])
+        }
+    }
+
+    fun createServiceMonitor(): HasMetadata {
+        val serviceMonitorContext = ResourceDefinitionContext.Builder()
+            .withGroup("monitoring.coreos.com")
+            .withKind("ServiceMonitor")
+            .withPlural("servicemonitors")
+            .withNamespaced(true)
+            .withVersion("v1")
+            .build()
+        server.registerResource(serviceMonitorContext)
+
+        val serviceMonitorStream = javaClass.getResourceAsStream("/k8s-resource-files/test-service-monitor.yaml")
+        return server.client.load(serviceMonitorStream).get()[0]
+    }
+}
diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactoryTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactoryTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..19d7c6cb3997d93d62908ebf4646f52d12b3d6d5
--- /dev/null
+++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactoryTest.kt
@@ -0,0 +1,81 @@
+package rocks.theodolite.kubernetes.patcher
+
+import io.quarkus.test.junit.QuarkusTest
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Test
+
+@QuarkusTest
+internal class PatcherFactoryTest {
+
+    @Test
+    fun testGenericResourcePatcherWithoutType() {
+        val patcherDefinition = PatcherDefinition()
+        patcherDefinition.type = "GenericResourcePatcher"
+        patcherDefinition.properties = mapOf(
+            "path" to "some/path/123/toSomeField"
+        )
+        val patcher = PatcherFactory.createPatcher(patcherDefinition)
+        assertTrue(patcher is GenericResourcePatcher)
+        val castedPatcher = patcher as GenericResourcePatcher
+        assertEquals(listOf("some", "path", 123, "toSomeField"), castedPatcher.path)
+        assertEquals(GenericResourcePatcher.Type.STRING, castedPatcher.type)
+    }
+
+    @Test
+    fun testGenericResourcePatcherWithStringType() {
+        val patcherDefinition = PatcherDefinition()
+        patcherDefinition.type = "GenericResourcePatcher"
+        patcherDefinition.properties = mapOf(
+            "path" to "spec",
+            "type" to "string"
+        )
+        val patcher = PatcherFactory.createPatcher(patcherDefinition)
+        assertTrue(patcher is GenericResourcePatcher)
+        val castedPatcher = patcher as GenericResourcePatcher
+        assertEquals(GenericResourcePatcher.Type.STRING, castedPatcher.type)
+    }
+
+    @Test
+    fun testGenericResourcePatcherWithBooleanType() {
+        val patcherDefinition = PatcherDefinition()
+        patcherDefinition.type = "GenericResourcePatcher"
+        patcherDefinition.properties = mapOf(
+            "path" to "spec",
+            "type" to "boolean"
+        )
+        val patcher = PatcherFactory.createPatcher(patcherDefinition)
+        assertTrue(patcher is GenericResourcePatcher)
+        val castedPatcher = patcher as GenericResourcePatcher
+        assertEquals(GenericResourcePatcher.Type.BOOLEAN, castedPatcher.type)
+    }
+
+    @Test
+    fun testGenericResourcePatcherWithIntegerType() {
+        val patcherDefinition = PatcherDefinition()
+        patcherDefinition.type = "GenericResourcePatcher"
+        patcherDefinition.properties = mapOf(
+            "path" to "spec",
+            "type" to "integer"
+        )
+        val patcher = PatcherFactory.createPatcher(patcherDefinition)
+        assertTrue(patcher is GenericResourcePatcher)
+        val castedPatcher = patcher as GenericResourcePatcher
+        assertEquals(GenericResourcePatcher.Type.INTEGER, castedPatcher.type)
+    }
+
+    @Test
+    fun testGenericResourcePatcherWithNumberType() {
+        val patcherDefinition = PatcherDefinition()
+        patcherDefinition.type = "GenericResourcePatcher"
+        patcherDefinition.properties = mapOf(
+            "path" to "spec",
+            "type" to "number"
+        )
+        val patcher = PatcherFactory.createPatcher(patcherDefinition)
+        assertTrue(patcher is GenericResourcePatcher)
+        val castedPatcher = patcher as GenericResourcePatcher
+        assertEquals(GenericResourcePatcher.Type.NUMBER, castedPatcher.type)
+    }
+
+}
\ No newline at end of file
diff --git a/theodolite/src/test/resources/k8s-resource-files/test-service-monitor.yaml b/theodolite/src/test/resources/k8s-resource-files/test-service-monitor.yaml
index e8a0e52e15245e790adf2cbf84edb517754267be..7afe8fe71e38ddd5e53116759a250d97b20af9ac 100644
--- a/theodolite/src/test/resources/k8s-resource-files/test-service-monitor.yaml
+++ b/theodolite/src/test/resources/k8s-resource-files/test-service-monitor.yaml
@@ -4,4 +4,11 @@ metadata:
   labels:
     app: titan-ccp-aggregation
     appScope: titan-ccp
-  name: test-service-monitor
\ No newline at end of file
+  name: test-service-monitor
+spec:
+  selector:
+    matchLabels:
+      app: flink
+  endpoints:
+    - port: metrics
+      interval: 10s
\ No newline at end of file