Search for custom serializers/deserializers/adapters in a deterministic way
diff --git a/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java b/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java
index 57948a4..c82ffbd 100644
--- a/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java
+++ b/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java
@@ -137,7 +137,6 @@
      * @param customization       with component info
      * @return serializer optional
      */
-    @SuppressWarnings("unchecked")
     public Optional<SerializerBinding<?>> getSerializerBinding(Type propertyRuntimeType,
                                                                ComponentBoundCustomization customization) {
 
@@ -154,7 +153,6 @@
      * @param customization       customization with component info
      * @return serializer optional
      */
-    @SuppressWarnings("unchecked")
     public Optional<DeserializerBinding<?>> getDeserializerBinding(Type propertyRuntimeType,
                                                                    ComponentBoundCustomization customization) {
         if (customization == null || customization.getDeserializerBinding() == null) {
@@ -196,12 +194,46 @@
     }
 
     private <T extends AbstractComponentBinding> Optional<T> searchComponentBinding(Type runtimeType, Function<ComponentBindings, T> supplier) {
-        for (ComponentBindings componentBindings : userComponents.values()) {
-            final T component = supplier.apply(componentBindings);
-            if (component != null && matches(runtimeType, componentBindings.getBindingType())) {
-                return Optional.of(component);
+        // First check if there is an exact match
+        ComponentBindings binding = userComponents.get(runtimeType);
+        if (binding != null) {
+            Optional<T> match = getMatchingBinding(runtimeType, binding, supplier);
+            if (match.isPresent()) {
+               return match;
             }
         }
+        
+        if (runtimeType instanceof Class) {
+            Class<?> runtimeClass = (Class<?>) runtimeType;
+            // Check if any interfaces have a match
+            for (Class<?> ifc : runtimeClass.getInterfaces()) {
+                ComponentBindings ifcBinding = userComponents.get(ifc);
+                if (ifcBinding != null) {
+                  Optional<T> match = getMatchingBinding(ifc, ifcBinding, supplier);
+                  if (match.isPresent()) {
+                      return match;
+                  }
+                }
+            }
+            
+            // check if the superclass has a match
+            Class<?> superClass = runtimeClass.getSuperclass();
+            if (superClass != null && superClass != Object.class) {
+                Optional<T> superBinding = searchComponentBinding(superClass, supplier);
+                if (superBinding.isPresent()) {
+                    return superBinding;
+                }
+            }
+        }
+        
+        return Optional.empty();
+    }
+    
+    private <T> Optional<T> getMatchingBinding(Type runtimeType, ComponentBindings binding, Function<ComponentBindings, T> supplier) {
+        final T component = supplier.apply(binding);
+        if (component != null && matches(runtimeType, binding.getBindingType())) {
+            return Optional.of(component);
+        }
         return Optional.empty();
     }
 
diff --git a/src/test/java/org/eclipse/yasson/serializers/SerializersTest.java b/src/test/java/org/eclipse/yasson/serializers/SerializersTest.java
index 8336d2f..506497f 100644
--- a/src/test/java/org/eclipse/yasson/serializers/SerializersTest.java
+++ b/src/test/java/org/eclipse/yasson/serializers/SerializersTest.java
@@ -12,11 +12,13 @@
 
 package org.eclipse.yasson.serializers;
 
-import org.junit.jupiter.api.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.eclipse.yasson.Jsonbs.*;
-
 import static java.util.Collections.singletonMap;
+import static org.eclipse.yasson.Jsonbs.defaultJsonb;
+import static org.eclipse.yasson.Jsonbs.nullableJsonb;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.StringReader;
 import java.lang.reflect.Type;
@@ -64,6 +66,7 @@
 import org.eclipse.yasson.serializers.model.SimpleContainer;
 import org.eclipse.yasson.serializers.model.StringWrapper;
 import org.eclipse.yasson.serializers.model.SupertypeSerializerPojo;
+import org.junit.jupiter.api.Test;
 
 /**
  * @author Roman Grigoriadi
@@ -514,4 +517,81 @@
         crateInner.crateInnerBigDec = BigDecimal.TEN;
         return crateInner;
     }
+    
+    public static class Foo { }
+
+    public static class Bar extends Foo { }
+    
+    public static class Baz extends Bar { }
+
+    public static class FooSerializer implements JsonbSerializer<Foo> {
+      public void serialize(Foo obj, JsonGenerator generator, SerializationContext ctx) {
+        generator.write("foo");
+      }
+    }
+
+    public static class BazSerializer implements JsonbSerializer<Baz> {
+      public void serialize(Baz obj, JsonGenerator generator, SerializationContext ctx) {
+        generator.write("baz");
+      }
+    }
+    
+    /**
+     * Test for issue: https://github.com/quarkusio/quarkus/issues/8925
+     * Ensure that if multiple customizations (serializer, deserializer, or adapter) are applied 
+     * for different types in the same class hierarchy, we use the customization for the most 
+     * specific type in the class hierarchy.
+     */
+    @Test
+    public void testSerializerMatching() {
+      Jsonb jsonb = JsonbBuilder.create(new JsonbConfig()
+          .withSerializers(new FooSerializer(), new BazSerializer()));
+      assertEquals("\"foo\"", jsonb.toJson(new Foo()));
+      // Since 'Bar' does not have its own serializer, it should use 
+      // the next serializer in the tree (FooSerializer)
+      assertEquals("\"foo\"", jsonb.toJson(new Bar()));
+      assertEquals("\"baz\"", jsonb.toJson(new Baz()));
+    }
+    
+    public static interface One { }
+    public static interface Two { }
+    public static interface Three { }
+    
+    public static class OneTwo implements One, Two { }
+    public static class OneTwoThree implements One, Two, Three { }
+    
+    public static class OneSerializer implements JsonbSerializer<One> {
+      public void serialize(One obj, JsonGenerator generator, SerializationContext ctx) {
+        generator.write("one");
+      }
+    }
+    
+    public static class TwoSerializer implements JsonbSerializer<Two> {
+      public void serialize(Two obj, JsonGenerator generator, SerializationContext ctx) {
+        generator.write("two");
+      }
+    }
+    
+    public static class ThreeSerializer implements JsonbSerializer<Three> {
+      public void serialize(Three obj, JsonGenerator generator, SerializationContext ctx) {
+        generator.write("three");
+      }
+    }
+    
+    @Test
+    public void testSerializerMatchingInterfaces01() {
+      Jsonb jsonb = JsonbBuilder.create(new JsonbConfig()
+          .withSerializers(new OneSerializer(), new TwoSerializer(), new ThreeSerializer()));
+      assertEquals("\"one\"", jsonb.toJson(new OneTwo()));
+      assertEquals("\"one\"", jsonb.toJson(new OneTwoThree()));
+    }
+    
+    @Test
+    public void testSerializerMatchingInterfaces02() {
+      Jsonb jsonb = JsonbBuilder.create(new JsonbConfig()
+          .withSerializers(new ThreeSerializer(), new TwoSerializer()));
+      assertEquals("\"two\"", jsonb.toJson(new OneTwo()));
+      assertEquals("\"two\"", jsonb.toJson(new OneTwoThree()));
+    }
+    
 }