This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 8d987d91e21f CAMEL-26300: camel-jackson and camel-jackson3 - 
application-json writes a Map, a List, text, bytes and a stream, avro-x-struct 
reads Json text, the Java object transformers fail clearly on a null body and 
read a JsonNode with Jackson 2 too, and the Jackson 3 Avro and Protobuf 
transformers wrap their errors (#29215)
8d987d91e21f is described below

commit 8d987d91e21f7e1a0b658b1030c4dd965e71c9a3
Author: Andrea Cosentino <[email protected]>
AuthorDate: Thu Nov 5 13:03:15 2026 +0100

    CAMEL-26300: camel-jackson and camel-jackson3 - application-json writes a 
Map, a List, text, bytes and a stream, avro-x-struct reads Json text, the Java 
object transformers fail clearly on a null body and read a JsonNode with 
Jackson 2 too, and the Jackson 3 Avro and Protobuf transformers wrap their 
errors (#29215)
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../catalog/transformers/application-json.json     |   6 +-
 .../catalog/transformers/avro-x-java-object.json   |   2 +-
 .../camel/catalog/transformers/avro-x-struct.json  |   3 +-
 .../transformers/protobuf-x-java-object.json       |   2 +-
 .../camel/transformer/avro-x-java-object.json      |   2 +-
 .../apache/camel/transformer/avro-x-struct.json    |   3 +-
 .../transform/AvroPojoDataTypeTransformer.java     |  14 ++-
 .../transform/AvroStructDataTypeTransformer.java   |  10 +-
 .../transform/AvroPojoDataTypeTransformerTest.java |  37 +++++-
 .../AvroStructDataTypeTransformerTest.java         |  46 ++++++--
 .../camel/transformer/protobuf-x-java-object.json  |   2 +-
 .../transform/ProtobufPojoDataTypeTransformer.java |   9 +-
 .../ProtobufStructDataTypeTransformer.java         |   2 +-
 .../ProtobufPojoDataTypeTransformerTest.java       |  37 +++++-
 .../ProtobufStructDataTypeTransformerTest.java     |  16 +++
 .../apache/camel/transformer/application-json.json |   6 +-
 .../jackson/transform/JsonDataTypeTransformer.java |  44 ++++++--
 .../transform/JsonPojoDataTypeTransformer.java     |   2 +-
 .../transform/JsonDataTypeTransformerTest.java     | 125 ++++++++++++++++++++-
 .../transform/JsonPojoDataTypeTransformerTest.java |  14 +++
 .../camel/transformer/avro-x-java-object.json      |   2 +-
 .../apache/camel/transformer/avro-x-struct.json    |   3 +-
 .../transform/AvroBinaryDataTypeTransformer.java   |   3 +-
 .../transform/AvroPojoDataTypeTransformer.java     |   9 +-
 .../transform/AvroStructDataTypeTransformer.java   |  13 ++-
 .../AvroBinaryDataTypeTransformerTest.java         |  12 ++
 .../transform/AvroPojoDataTypeTransformerTest.java |  37 +++++-
 .../AvroStructDataTypeTransformerTest.java         |  53 ++++++---
 .../camel/transformer/protobuf-x-java-object.json  |   2 +-
 .../ProtobufBinaryDataTypeTransformer.java         |   3 +-
 .../transform/ProtobufPojoDataTypeTransformer.java |   4 +-
 .../ProtobufStructDataTypeTransformer.java         |   5 +-
 .../ProtobufBinaryDataTypeTransformerTest.java     |  12 ++
 .../ProtobufPojoDataTypeTransformerTest.java       |  37 +++++-
 .../ProtobufStructDataTypeTransformerTest.java     |  28 +++++
 .../apache/camel/transformer/application-json.json |   6 +-
 .../transform/JsonDataTypeTransformer.java         |  44 ++++++--
 .../transform/JsonPojoDataTypeTransformer.java     |   2 +-
 .../transform/JsonDataTypeTransformerTest.java     | 125 ++++++++++++++++++++-
 .../transform/JsonPojoDataTypeTransformerTest.java |  14 +++
 .../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc    |  33 ++++++
 41 files changed, 722 insertions(+), 107 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/application-json.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/application-json.json
index 1cfae9b4ccfd..3e35142d8732 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/application-json.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/application-json.json
@@ -14,10 +14,14 @@
     "transformerIn": {
       "carriers": [
         "text",
+        "bytes",
+        "stream",
+        "map",
+        "list",
         "pojo",
         "null"
       ],
-      "description": "A Json object or array as text, a JsonNode or a POJO, of 
the class of the X-Content-Class exchange property when set: other text, bytes, 
a stream, a Map or a List fail, and a null body becomes null"
+      "description": "A Json object or array as text, bytes or a stream, a 
Map, a List, a JsonNode or a POJO; other text, also a Json number, boolean, 
null or quoted string, becomes a Json string; bytes and a stream are read as 
text with the exchange charset, so a payload that is not text must be encoded 
first, such as in Base64, or given a content class; with the X-Content-Class 
exchange property only a Json object or array as text or a body of that class; 
a null body becomes null"
     },
     "transformerOut": {
       "carriers": [
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/avro-x-java-object.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/avro-x-java-object.json
index f03ee1231688..e679b539ff22 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/avro-x-java-object.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/avro-x-java-object.json
@@ -19,7 +19,7 @@
         "file",
         "pojo"
       ],
-      "description": "Json text, or Avro binary with the Avro schema in the 
X-Content-Schema exchange property, read into the class of the X-Content-Class 
exchange property, which a body other than a POJO needs: a POJO of that class, 
or any POJO without it, is kept, and a Map or a null body fail"
+      "description": "Json text or a JsonNode, or Avro binary with the Avro 
schema in the X-Content-Schema exchange property, read into the class of the 
X-Content-Class exchange property, which a body other than a POJO needs: a POJO 
of that class, or any POJO without it, is kept, and a Map or a null body fail"
     },
     "transformerOut": {
       "carriers": [
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/avro-x-struct.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/avro-x-struct.json
index 001eec1a900a..915f2f8418b4 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/avro-x-struct.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/avro-x-struct.json
@@ -13,12 +13,13 @@
   "bodyTypes": {
     "transformerIn": {
       "carriers": [
+        "text",
         "bytes",
         "stream",
         "file",
         "pojo"
       ],
-      "description": "Needs the Avro schema in the X-Content-Schema exchange 
property: Avro binary, a JsonNode or a POJO; Json text, a Map or a null body 
fail"
+      "description": "Needs the Avro schema in the X-Content-Schema exchange 
property: a Json object or array as text, Avro binary, a JsonNode or a POJO; a 
Map or a null body fail"
     },
     "transformerOut": {
       "carriers": [
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/protobuf-x-java-object.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/protobuf-x-java-object.json
index 4d9d4a164a20..eb133e1b7fa2 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/protobuf-x-java-object.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/protobuf-x-java-object.json
@@ -19,7 +19,7 @@
         "file",
         "pojo"
       ],
-      "description": "Json text, or Protobuf binary with the Protobuf schema 
in the X-Content-Schema exchange property, read into the class of the 
X-Content-Class exchange property, which a body other than a POJO needs: a POJO 
of that class, or any POJO without it, is kept, and a Map or a null body fail"
+      "description": "Json text or a JsonNode, or Protobuf binary with the 
Protobuf schema in the X-Content-Schema exchange property, read into the class 
of the X-Content-Class exchange property, which a body other than a POJO needs: 
a POJO of that class, or any POJO without it, is kept, and a Map or a null body 
fail"
     },
     "transformerOut": {
       "carriers": [
diff --git 
a/components/camel-jackson-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-java-object.json
 
b/components/camel-jackson-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-java-object.json
index f03ee1231688..e679b539ff22 100644
--- 
a/components/camel-jackson-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-java-object.json
+++ 
b/components/camel-jackson-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-java-object.json
@@ -19,7 +19,7 @@
         "file",
         "pojo"
       ],
-      "description": "Json text, or Avro binary with the Avro schema in the 
X-Content-Schema exchange property, read into the class of the X-Content-Class 
exchange property, which a body other than a POJO needs: a POJO of that class, 
or any POJO without it, is kept, and a Map or a null body fail"
+      "description": "Json text or a JsonNode, or Avro binary with the Avro 
schema in the X-Content-Schema exchange property, read into the class of the 
X-Content-Class exchange property, which a body other than a POJO needs: a POJO 
of that class, or any POJO without it, is kept, and a Map or a null body fail"
     },
     "transformerOut": {
       "carriers": [
diff --git 
a/components/camel-jackson-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-struct.json
 
b/components/camel-jackson-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-struct.json
index 001eec1a900a..915f2f8418b4 100644
--- 
a/components/camel-jackson-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-struct.json
+++ 
b/components/camel-jackson-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-struct.json
@@ -13,12 +13,13 @@
   "bodyTypes": {
     "transformerIn": {
       "carriers": [
+        "text",
         "bytes",
         "stream",
         "file",
         "pojo"
       ],
-      "description": "Needs the Avro schema in the X-Content-Schema exchange 
property: Avro binary, a JsonNode or a POJO; Json text, a Map or a null body 
fail"
+      "description": "Needs the Avro schema in the X-Content-Schema exchange 
property: a Json object or array as text, Avro binary, a JsonNode or a POJO; a 
Map or a null body fail"
     },
     "transformerOut": {
       "carriers": [
diff --git 
a/components/camel-jackson-avro/src/main/java/org/apache/camel/component/jackson/avro/transform/AvroPojoDataTypeTransformer.java
 
b/components/camel-jackson-avro/src/main/java/org/apache/camel/component/jackson/avro/transform/AvroPojoDataTypeTransformer.java
index 6daeddacee10..5e22ddf17e76 100644
--- 
a/components/camel-jackson-avro/src/main/java/org/apache/camel/component/jackson/avro/transform/AvroPojoDataTypeTransformer.java
+++ 
b/components/camel-jackson-avro/src/main/java/org/apache/camel/component/jackson/avro/transform/AvroPojoDataTypeTransformer.java
@@ -39,10 +39,11 @@ import org.apache.camel.spi.DataTypeTransformer;
 @DataTypeTransformer(name = "avro-x-java-object",
                      description = "Transforms from JSon to Java object using 
Jackson Avro (supports content schema)")
 @BodyTypes(transformerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.POJO },
-                                     description = "Json text, or Avro binary 
with the Avro schema in the X-Content-Schema"
-                                                   + " exchange property, read 
into the class of the X-Content-Class exchange"
-                                                   + " property, which a body 
other than a POJO needs: a POJO of that class,"
-                                                   + " or any POJO without it, 
is kept, and a Map or a null body fail"),
+                                     description = "Json text or a JsonNode, 
or Avro binary with the Avro schema in the"
+                                                   + " X-Content-Schema 
exchange property, read into the class of the"
+                                                   + " X-Content-Class 
exchange property, which a body other than a POJO"
+                                                   + " needs: a POJO of that 
class, or any POJO without it, is kept, and a"
+                                                   + " Map or a null body 
fail"),
            transformerOut = @BodyType(value = Carrier.UNKNOWN,
                                       description = "An object of the class of 
the X-Content-Class exchange property"))
 public class AvroPojoDataTypeTransformer extends JsonPojoDataTypeTransformer {
@@ -60,8 +61,9 @@ public class AvroPojoDataTypeTransformer extends 
JsonPojoDataTypeTransformer {
                         "Missing proper Avro schema for Java object data type 
processing", message.getExchange());
             }
 
-            if (message.getBody() instanceof JsonNode) {
-                return 
Avro.mapper().reader().forType(contentType).with(schema).readValue(message.getBody(JsonNode.class));
+            if (message.getBody() instanceof JsonNode jsonNode) {
+                // the parser of a JsonNode takes no Avro schema
+                return 
Avro.mapper().reader().forType(contentType).readValue(jsonNode);
             }
 
             return 
Avro.mapper().reader().forType(contentType).with(schema).readValue(getBodyAsStream(message));
diff --git 
a/components/camel-jackson-avro/src/main/java/org/apache/camel/component/jackson/avro/transform/AvroStructDataTypeTransformer.java
 
b/components/camel-jackson-avro/src/main/java/org/apache/camel/component/jackson/avro/transform/AvroStructDataTypeTransformer.java
index 23bdafb33d17..e44586f249b8 100644
--- 
a/components/camel-jackson-avro/src/main/java/org/apache/camel/component/jackson/avro/transform/AvroStructDataTypeTransformer.java
+++ 
b/components/camel-jackson-avro/src/main/java/org/apache/camel/component/jackson/avro/transform/AvroStructDataTypeTransformer.java
@@ -27,6 +27,7 @@ import org.apache.camel.Exchange;
 import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.Message;
 import org.apache.camel.component.jackson.SchemaHelper;
+import org.apache.camel.component.jackson.transform.Json;
 import org.apache.camel.spi.BodyType;
 import org.apache.camel.spi.BodyType.Carrier;
 import org.apache.camel.spi.BodyTypes;
@@ -41,9 +42,10 @@ import org.apache.camel.spi.Transformer;
  */
 @DataTypeTransformer(name = "avro-x-struct",
                      description = "Transforms to generic JSonNode using 
Jackson Avro (supports content schema)")
-@BodyTypes(transformerIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, 
Carrier.FILE, Carrier.POJO },
-                                     description = "Needs the Avro schema in 
the X-Content-Schema exchange property: Avro"
-                                                   + " binary, a JsonNode or a 
POJO; Json text, a Map or a null body fail"),
+@BodyTypes(transformerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.POJO },
+                                     description = "Needs the Avro schema in 
the X-Content-Schema exchange property: a Json"
+                                                   + " object or array as 
text, Avro binary, a JsonNode or a POJO; a Map or a"
+                                                   + " null body fail"),
            transformerOut = @BodyType(value = Carrier.POJO, javaType = 
"com.fasterxml.jackson.databind.JsonNode"))
 public class AvroStructDataTypeTransformer extends Transformer {
 
@@ -63,6 +65,8 @@ public class AvroStructDataTypeTransformer extends 
Transformer {
                         = 
message.getExchange().getContext().getClassResolver().resolveMandatoryClass(contentClass);
                 unmarshalled = 
Avro.mapper().reader().forType(JsonNode.class).with(schema)
                         
.readValue(Avro.mapper().writerFor(contentType).with(schema).writeValueAsBytes(message.getBody()));
+            } else if (message.getBody() instanceof String jsonString && 
Json.isJson(jsonString)) {
+                unmarshalled = Json.mapper().readTree(jsonString);
             } else {
                 unmarshalled = 
Avro.mapper().reader().forType(JsonNode.class).with(schema).readValue(getBodyAsStream(message));
             }
diff --git 
a/components/camel-jackson-avro/src/test/java/org/apache/camel/component/jackson/avro/transform/AvroPojoDataTypeTransformerTest.java
 
b/components/camel-jackson-avro/src/test/java/org/apache/camel/component/jackson/avro/transform/AvroPojoDataTypeTransformerTest.java
index edcb75fab926..f2d92aca2a00 100644
--- 
a/components/camel-jackson-avro/src/test/java/org/apache/camel/component/jackson/avro/transform/AvroPojoDataTypeTransformerTest.java
+++ 
b/components/camel-jackson-avro/src/test/java/org/apache/camel/component/jackson/avro/transform/AvroPojoDataTypeTransformerTest.java
@@ -31,6 +31,7 @@ import org.apache.avro.NameValidator;
 import org.apache.avro.Schema;
 import org.apache.camel.CamelExecutionException;
 import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.component.jackson.SchemaHelper;
 import org.apache.camel.component.jackson.transform.Json;
 import org.apache.camel.impl.DefaultCamelContext;
@@ -136,6 +137,35 @@ class AvroPojoDataTypeTransformerTest {
         Assertions.assertEquals(19, 
exchange.getMessage().getBody(Person.class).age());
     }
 
+    @Test
+    void shouldHandleJsonNode() throws Exception {
+        // CAMEL-26300: a JsonNode is read into the class of the 
X-Content-Class property, with the Avro schema set
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
+        
exchange.getMessage().setBody(Json.mapper().readerFor(JsonNode.class).readValue("""
+                    { "name": "Goofy", "age": 25 }
+                """));
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        Assertions.assertEquals(new Person("Goofy", 25), 
exchange.getMessage().getBody());
+    }
+
+    @Test
+    void shouldFailOnNullBody() throws Exception {
+        // CAMEL-26300: a null body has no Avro binary to read, which fails as 
other bodies without it do
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
+        exchange.getMessage().setBody(null);
+
+        CamelExecutionException e = 
Assertions.assertThrows(CamelExecutionException.class,
+                () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
+        Assertions.assertInstanceOf(InvalidPayloadException.class, 
e.getCause());
+    }
+
     @Test
     public void shouldLookupDataTypeTransformer() throws Exception {
         Transformer transformer = camelContext.getTransformerRegistry()
@@ -152,8 +182,8 @@ class AvroPojoDataTypeTransformerTest {
 
     @Test
     void theBodyTypesSayTheBody(@TempDir Path dir) throws Exception {
-        // CAMEL-25928: Json text, or Avro binary as bytes, a stream or a 
file, as transformerIn says, read into the
-        // class of the X-Content-Class property, which transformerOut leaves 
unknown
+        // CAMEL-25928: Json text or a JsonNode, or Avro binary as bytes, a 
stream or a file, as transformerIn
+        // says, read into the class of the X-Content-Class property, which 
transformerOut leaves unknown
         BodyTypes bodyTypes = 
AvroPojoDataTypeTransformer.class.getAnnotation(BodyTypes.class);
         Assertions.assertEquals(List.of(Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.POJO),
                 List.of(bodyTypes.transformerIn().value()));
@@ -161,7 +191,8 @@ class AvroPojoDataTypeTransformerTest {
         String json = "{ \"name\": \"Goofy\", \"age\": 25 }";
         byte[] binary = 
Avro.mapper().writer(getSchema()).writeValueAsBytes(new Person("Goofy", 25));
         Path file = Files.write(dir.resolve("person.bin"), binary);
-        for (Object body : Arrays.asList(json, binary, new 
ByteArrayInputStream(binary), file.toFile())) {
+        for (Object body : Arrays.asList(json, binary, new 
ByteArrayInputStream(binary), file.toFile(),
+                Json.mapper().readerFor(JsonNode.class).readValue(json))) {
             Exchange exchange = new DefaultExchange(camelContext);
             exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
             exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
diff --git 
a/components/camel-jackson-avro/src/test/java/org/apache/camel/component/jackson/avro/transform/AvroStructDataTypeTransformerTest.java
 
b/components/camel-jackson-avro/src/test/java/org/apache/camel/component/jackson/avro/transform/AvroStructDataTypeTransformerTest.java
index 4e10a27cae7b..1e31f2c404a0 100644
--- 
a/components/camel-jackson-avro/src/test/java/org/apache/camel/component/jackson/avro/transform/AvroStructDataTypeTransformerTest.java
+++ 
b/components/camel-jackson-avro/src/test/java/org/apache/camel/component/jackson/avro/transform/AvroStructDataTypeTransformerTest.java
@@ -19,6 +19,7 @@ package org.apache.camel.component.jackson.avro.transform;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Arrays;
@@ -64,6 +65,7 @@ class AvroStructDataTypeTransformerTest {
 
     @Test
     void shouldHandleJsonString() throws Exception {
+        // CAMEL-26300: Json text is read as Json, not as Avro binary
         Exchange exchange = new DefaultExchange(camelContext);
 
         AvroSchema avroSchema = getSchema();
@@ -74,6 +76,36 @@ class AvroStructDataTypeTransformerTest {
         transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
 
         Assertions.assertEquals(ObjectNode.class, 
exchange.getMessage().getBody().getClass());
+        JsonNode body = exchange.getMessage().getBody(JsonNode.class);
+        Assertions.assertEquals("Christoph", body.get("name").asText());
+        Assertions.assertEquals(32, body.get("age").asInt());
+    }
+
+    @Test
+    void shouldWrapMalformedJsonInCamelExecutionException() throws Exception {
+        // CAMEL-26300: text that looks like Json is read as Json, and fails 
as Json
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.getMessage().setBody("{ this is no json }");
+
+        Assertions.assertThrows(CamelExecutionException.class,
+                () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
+    }
+
+    @Test
+    void shouldReadJsonStringWhateverTheExchangeCharset() throws Exception {
+        // CAMEL-26300: Json text is read as the String it is, so a non-ASCII 
character works with any exchange charset
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.setProperty(Exchange.CHARSET_NAME, 
StandardCharsets.ISO_8859_1.name());
+        exchange.getMessage().setBody("{ \"name\": \"Jos\u00e9\", \"age\": 32 
}");
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        JsonNode body = exchange.getMessage().getBody(JsonNode.class);
+        Assertions.assertEquals("Jos\u00e9", body.get("name").asText());
+        Assertions.assertEquals(32, body.get("age").asInt());
     }
 
     @Test
@@ -131,17 +163,17 @@ class AvroStructDataTypeTransformerTest {
 
     @Test
     void theBodyTypesSayTheBody(@TempDir Path dir) throws Exception {
-        // CAMEL-25928: Avro binary as bytes, a stream or a file, a POJO or a 
JsonNode, as transformerIn says, and
-        // the JsonNode transformerOut says
+        // CAMEL-25928: Json text, Avro binary as bytes, a stream or a file, a 
POJO or a JsonNode, as transformerIn
+        // says, and the JsonNode transformerOut says
         BodyTypes bodyTypes = 
AvroStructDataTypeTransformer.class.getAnnotation(BodyTypes.class);
-        Assertions.assertEquals(List.of(Carrier.BYTES, Carrier.STREAM, 
Carrier.FILE, Carrier.POJO),
+        Assertions.assertEquals(List.of(Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.POJO),
                 List.of(bodyTypes.transformerIn().value()));
         Assertions.assertEquals(List.of(Carrier.POJO), 
List.of(bodyTypes.transformerOut().value()));
         Assertions.assertEquals(JsonNode.class.getName(), 
bodyTypes.transformerOut().javaType());
         String json = "{ \"name\": \"Goofy\", \"age\": 25 }";
         byte[] binary = 
Avro.mapper().writer(getSchema()).writeValueAsBytes(new Person("Goofy", 25));
         Path file = Files.write(dir.resolve("person.bin"), binary);
-        for (Object body : Arrays.asList(binary, new 
ByteArrayInputStream(binary), file.toFile(), new Person("Goofy", 25),
+        for (Object body : Arrays.asList(json, binary, new 
ByteArrayInputStream(binary), file.toFile(), new Person("Goofy", 25),
                 Json.mapper().readerFor(JsonNode.class).readValue(json))) {
             Exchange exchange = new DefaultExchange(camelContext);
             exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
@@ -155,11 +187,5 @@ class AvroStructDataTypeTransformerTest {
         other.getMessage().setBody(Map.of("name", "Goofy"));
         Assertions.assertThrows(CamelExecutionException.class,
                 () -> transformer.transform(other.getMessage(), DataType.ANY, 
DataType.ANY));
-        // nor is Json text
-        Exchange text = new DefaultExchange(camelContext);
-        text.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
-        text.getMessage().setBody(json);
-        Assertions.assertThrows(RuntimeException.class,
-                () -> transformer.transform(text.getMessage(), DataType.ANY, 
DataType.ANY));
     }
 }
diff --git 
a/components/camel-jackson-protobuf/src/generated/resources/META-INF/services/org/apache/camel/transformer/protobuf-x-java-object.json
 
b/components/camel-jackson-protobuf/src/generated/resources/META-INF/services/org/apache/camel/transformer/protobuf-x-java-object.json
index 4d9d4a164a20..eb133e1b7fa2 100644
--- 
a/components/camel-jackson-protobuf/src/generated/resources/META-INF/services/org/apache/camel/transformer/protobuf-x-java-object.json
+++ 
b/components/camel-jackson-protobuf/src/generated/resources/META-INF/services/org/apache/camel/transformer/protobuf-x-java-object.json
@@ -19,7 +19,7 @@
         "file",
         "pojo"
       ],
-      "description": "Json text, or Protobuf binary with the Protobuf schema 
in the X-Content-Schema exchange property, read into the class of the 
X-Content-Class exchange property, which a body other than a POJO needs: a POJO 
of that class, or any POJO without it, is kept, and a Map or a null body fail"
+      "description": "Json text or a JsonNode, or Protobuf binary with the 
Protobuf schema in the X-Content-Schema exchange property, read into the class 
of the X-Content-Class exchange property, which a body other than a POJO needs: 
a POJO of that class, or any POJO without it, is kept, and a Map or a null body 
fail"
     },
     "transformerOut": {
       "carriers": [
diff --git 
a/components/camel-jackson-protobuf/src/main/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufPojoDataTypeTransformer.java
 
b/components/camel-jackson-protobuf/src/main/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufPojoDataTypeTransformer.java
index 051abeff6462..3bfa0f80a6d5 100644
--- 
a/components/camel-jackson-protobuf/src/main/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufPojoDataTypeTransformer.java
+++ 
b/components/camel-jackson-protobuf/src/main/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufPojoDataTypeTransformer.java
@@ -39,8 +39,8 @@ import org.apache.camel.spi.DataTypeTransformer;
 @DataTypeTransformer(name = "protobuf-x-java-object",
                      description = "Transforms from JSon to Java object using 
Jackson Protobuf (supports content schema)")
 @BodyTypes(transformerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.POJO },
-                                     description = "Json text, or Protobuf 
binary with the Protobuf schema in the"
-                                                   + " X-Content-Schema 
exchange property, read into the class of the"
+                                     description = "Json text or a JsonNode, 
or Protobuf binary with the Protobuf schema"
+                                                   + " in the X-Content-Schema 
exchange property, read into the class of the"
                                                    + " X-Content-Class 
exchange property, which a body other than a POJO"
                                                    + " needs: a POJO of that 
class, or any POJO without it, is kept, and a"
                                                    + " Map or a null body 
fail"),
@@ -61,8 +61,9 @@ public class ProtobufPojoDataTypeTransformer extends 
JsonPojoDataTypeTransformer
                         "Missing proper Protobuf schema for Java object data 
type processing", message.getExchange());
             }
 
-            if (message.getBody() instanceof JsonNode) {
-                return 
Protobuf.mapper().reader().forType(contentType).with(schema).readValue(message.getBody(JsonNode.class));
+            if (message.getBody() instanceof JsonNode jsonNode) {
+                // the parser of a JsonNode takes no Protobuf schema
+                return 
Protobuf.mapper().reader().forType(contentType).readValue(jsonNode);
             }
 
             return 
Protobuf.mapper().reader().forType(contentType).with(schema).readValue(getBodyAsStream(message));
diff --git 
a/components/camel-jackson-protobuf/src/main/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufStructDataTypeTransformer.java
 
b/components/camel-jackson-protobuf/src/main/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufStructDataTypeTransformer.java
index b2997899d881..d17d3d9c8f2b 100644
--- 
a/components/camel-jackson-protobuf/src/main/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufStructDataTypeTransformer.java
+++ 
b/components/camel-jackson-protobuf/src/main/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufStructDataTypeTransformer.java
@@ -66,7 +66,7 @@ public class ProtobufStructDataTypeTransformer extends 
Transformer {
                 unmarshalled = 
Protobuf.mapper().reader().forType(JsonNode.class).with(schema)
                         
.readValue(Protobuf.mapper().writerFor(contentType).with(schema).writeValueAsBytes(message.getBody()));
             } else if (message.getBody() instanceof String jsonString && 
Json.isJson(jsonString)) {
-                unmarshalled = 
Json.mapper().readTree(getBodyAsStream(message));
+                unmarshalled = Json.mapper().readTree(jsonString);
             } else {
                 unmarshalled
                         = 
Protobuf.mapper().reader().forType(JsonNode.class).with(schema).readValue(getBodyAsStream(message));
diff --git 
a/components/camel-jackson-protobuf/src/test/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufPojoDataTypeTransformerTest.java
 
b/components/camel-jackson-protobuf/src/test/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufPojoDataTypeTransformerTest.java
index 836446ad74c2..a238eade2c68 100644
--- 
a/components/camel-jackson-protobuf/src/test/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufPojoDataTypeTransformerTest.java
+++ 
b/components/camel-jackson-protobuf/src/test/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufPojoDataTypeTransformerTest.java
@@ -29,6 +29,7 @@ import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.dataformat.protobuf.schema.ProtobufSchema;
 import org.apache.camel.CamelExecutionException;
 import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.component.jackson.SchemaHelper;
 import org.apache.camel.component.jackson.transform.Json;
 import org.apache.camel.impl.DefaultCamelContext;
@@ -134,6 +135,35 @@ class ProtobufPojoDataTypeTransformerTest {
         Assertions.assertEquals(19, 
exchange.getMessage().getBody(Person.class).age());
     }
 
+    @Test
+    void shouldHandleJsonNode() throws Exception {
+        // CAMEL-26300: a JsonNode is read into the class of the 
X-Content-Class property, with the Protobuf schema set
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
+        
exchange.getMessage().setBody(Json.mapper().readerFor(JsonNode.class).readValue("""
+                    { "name": "Goofy", "age": 25 }
+                """));
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        Assertions.assertEquals(new Person("Goofy", 25), 
exchange.getMessage().getBody());
+    }
+
+    @Test
+    void shouldFailOnNullBody() throws Exception {
+        // CAMEL-26300: a null body has no Protobuf binary to read, which 
fails as other bodies without it do
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
+        exchange.getMessage().setBody(null);
+
+        CamelExecutionException e = 
Assertions.assertThrows(CamelExecutionException.class,
+                () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
+        Assertions.assertInstanceOf(InvalidPayloadException.class, 
e.getCause());
+    }
+
     @Test
     public void shouldLookupDataTypeTransformer() throws Exception {
         Transformer transformer = camelContext.getTransformerRegistry()
@@ -149,8 +179,8 @@ class ProtobufPojoDataTypeTransformerTest {
 
     @Test
     void theBodyTypesSayTheBody(@TempDir Path dir) throws Exception {
-        // CAMEL-25928: Json text, or Protobuf binary as bytes, a stream or a 
file, as transformerIn says, read into the
-        // class of the X-Content-Class property, which transformerOut leaves 
unknown
+        // CAMEL-25928: Json text or a JsonNode, or Protobuf binary as bytes, 
a stream or a file, as transformerIn
+        // says, read into the class of the X-Content-Class property, which 
transformerOut leaves unknown
         BodyTypes bodyTypes = 
ProtobufPojoDataTypeTransformer.class.getAnnotation(BodyTypes.class);
         Assertions.assertEquals(List.of(Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.POJO),
                 List.of(bodyTypes.transformerIn().value()));
@@ -158,7 +188,8 @@ class ProtobufPojoDataTypeTransformerTest {
         String json = "{ \"name\": \"Goofy\", \"age\": 25 }";
         byte[] binary = 
Protobuf.mapper().writer(getSchema()).writeValueAsBytes(new Person("Goofy", 
25));
         Path file = Files.write(dir.resolve("person.bin"), binary);
-        for (Object body : Arrays.asList(json, binary, new 
ByteArrayInputStream(binary), file.toFile())) {
+        for (Object body : Arrays.asList(json, binary, new 
ByteArrayInputStream(binary), file.toFile(),
+                Json.mapper().readerFor(JsonNode.class).readValue(json))) {
             Exchange exchange = new DefaultExchange(camelContext);
             exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
             exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
diff --git 
a/components/camel-jackson-protobuf/src/test/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufStructDataTypeTransformerTest.java
 
b/components/camel-jackson-protobuf/src/test/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufStructDataTypeTransformerTest.java
index e3346a6bebae..8da716e59e4e 100644
--- 
a/components/camel-jackson-protobuf/src/test/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufStructDataTypeTransformerTest.java
+++ 
b/components/camel-jackson-protobuf/src/test/java/org/apache/camel/component/jackson/protobuf/transform/ProtobufStructDataTypeTransformerTest.java
@@ -19,6 +19,7 @@ package org.apache.camel.component.jackson.protobuf.transform;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Arrays;
@@ -75,6 +76,21 @@ class ProtobufStructDataTypeTransformerTest {
         Assertions.assertEquals(ObjectNode.class, 
exchange.getMessage().getBody().getClass());
     }
 
+    @Test
+    void shouldReadJsonStringWhateverTheExchangeCharset() throws Exception {
+        // CAMEL-26300: Json text is read as the String it is, so a non-ASCII 
character works with any exchange charset
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.setProperty(Exchange.CHARSET_NAME, 
StandardCharsets.ISO_8859_1.name());
+        exchange.getMessage().setBody("{ \"name\": \"Jos\u00e9\", \"age\": 32 
}");
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        JsonNode body = exchange.getMessage().getBody(JsonNode.class);
+        Assertions.assertEquals("Jos\u00e9", body.get("name").asText());
+        Assertions.assertEquals(32, body.get("age").asInt());
+    }
+
     @Test
     void shouldHandlePojo() throws Exception {
         Exchange exchange = new DefaultExchange(camelContext);
diff --git 
a/components/camel-jackson/src/generated/resources/META-INF/services/org/apache/camel/transformer/application-json.json
 
b/components/camel-jackson/src/generated/resources/META-INF/services/org/apache/camel/transformer/application-json.json
index 1cfae9b4ccfd..3e35142d8732 100644
--- 
a/components/camel-jackson/src/generated/resources/META-INF/services/org/apache/camel/transformer/application-json.json
+++ 
b/components/camel-jackson/src/generated/resources/META-INF/services/org/apache/camel/transformer/application-json.json
@@ -14,10 +14,14 @@
     "transformerIn": {
       "carriers": [
         "text",
+        "bytes",
+        "stream",
+        "map",
+        "list",
         "pojo",
         "null"
       ],
-      "description": "A Json object or array as text, a JsonNode or a POJO, of 
the class of the X-Content-Class exchange property when set: other text, bytes, 
a stream, a Map or a List fail, and a null body becomes null"
+      "description": "A Json object or array as text, bytes or a stream, a 
Map, a List, a JsonNode or a POJO; other text, also a Json number, boolean, 
null or quoted string, becomes a Json string; bytes and a stream are read as 
text with the exchange charset, so a payload that is not text must be encoded 
first, such as in Base64, or given a content class; with the X-Content-Class 
exchange property only a Json object or array as text or a body of that class; 
a null body becomes null"
     },
     "transformerOut": {
       "carriers": [
diff --git 
a/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/transform/JsonDataTypeTransformer.java
 
b/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/transform/JsonDataTypeTransformer.java
index ee9fba6f6c92..d451c1559983 100644
--- 
a/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/transform/JsonDataTypeTransformer.java
+++ 
b/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/transform/JsonDataTypeTransformer.java
@@ -16,12 +16,17 @@
  */
 package org.apache.camel.component.jackson.transform;
 
+import java.io.InputStream;
+import java.io.Reader;
 import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.Map;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import org.apache.camel.CamelExecutionException;
 import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.Message;
 import org.apache.camel.component.jackson.SchemaHelper;
 import org.apache.camel.spi.BodyType;
@@ -34,14 +39,20 @@ import org.apache.camel.spi.Transformer;
 
 /**
  * Data type uses Jackson data format to marshal given Exchange payload to a 
Json (binary byte array representation).
- * Requires Exchange payload as JsonNode representation.
+ * Json text is kept, other text becomes a Json string, and a Map, a List, a 
JsonNode or a POJO is written as Json.
+ * Bytes and a stream are read as text with the charset of the exchange.
  */
 @DataTypeTransformer(name = "application-json",
                      description = "Transforms from JSon to binary (byte 
array) using Jackson")
-@BodyTypes(transformerIn = @BodyType(value = { Carrier.TEXT, Carrier.POJO, 
Carrier.NULL },
-                                     description = "A Json object or array as 
text, a JsonNode or a POJO, of the class of"
-                                                   + " the X-Content-Class 
exchange property when set: other text, bytes, a"
-                                                   + " stream, a Map or a List 
fail, and a null body becomes null"),
+@BodyTypes(transformerIn = @BodyType(value = {
+        Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.MAP, 
Carrier.LIST, Carrier.POJO, Carrier.NULL },
+                                     description = "A Json object or array as 
text, bytes or a stream, a Map, a List, a"
+                                                   + " JsonNode or a POJO; 
other text, also a Json number, boolean, null or"
+                                                   + " quoted string, becomes 
a Json string; bytes and a stream are read as"
+                                                   + " text with the exchange 
charset, so a payload that is not text must be"
+                                                   + " encoded first, such as 
in Base64, or given a content class; with the"
+                                                   + " X-Content-Class 
exchange property only a Json object or array as text"
+                                                   + " or a body of that 
class; a null body becomes null"),
            transformerOut = @BodyType(value = Carrier.BYTES, javaType = 
"byte[]", format = "json"))
 public class JsonDataTypeTransformer extends Transformer {
 
@@ -49,14 +60,24 @@ public class JsonDataTypeTransformer extends Transformer {
     public void transform(Message message, DataType fromType, DataType toType) 
{
         try {
             byte[] marshalled;
-            if (message.getBody() instanceof String jsonString && 
Json.isJson(jsonString)) {
+            Object body = message.getBody();
+            boolean hasContentClass = 
message.getExchange().getProperty(SchemaHelper.CONTENT_CLASS, String.class) != 
null;
+            if (body instanceof String jsonString && Json.isJson(jsonString)) {
                 marshalled = jsonString.getBytes(StandardCharsets.UTF_8);
+            } else if (!hasContentClass && (body instanceof Map || body 
instanceof Collection)) {
+                // a Map or a List has no class to write it as: it becomes a 
Json object or array
+                marshalled = Json.mapper().writeValueAsBytes(body);
+            } else if (!hasContentClass && isText(body)) {
+                // read as text with the exchange charset: a Json object or 
array is kept, and any other text, also a
+                // Json number, boolean, null or quoted string, becomes a Json 
string
+                String text = message.getMandatoryBody(String.class);
+                marshalled = Json.isJson(text) ? 
text.getBytes(StandardCharsets.UTF_8) : Json.mapper().writeValueAsBytes(text);
             } else {
                 String contentClass = 
SchemaHelper.resolveContentClass(message.getExchange(), 
JsonNode.class.getName());
                 Class<?> contentType
                         = 
message.getExchange().getContext().getClassResolver().resolveMandatoryClass(contentClass);
 
-                marshalled = 
Json.mapper().writer().forType(contentType).writeValueAsBytes(message.getBody());
+                marshalled = 
Json.mapper().writer().forType(contentType).writeValueAsBytes(body);
             }
             message.setBody(marshalled);
 
@@ -66,8 +87,15 @@ public class JsonDataTypeTransformer extends Transformer {
             if (contentSchema != null) {
                 message.setHeader(SchemaHelper.CONTENT_SCHEMA, contentSchema);
             }
-        } catch (JsonProcessingException | ClassNotFoundException e) {
+        } catch (InvalidPayloadException | JsonProcessingException | 
ClassNotFoundException e) {
             throw new CamelExecutionException("Failed to apply Json output 
data type on exchange", message.getExchange(), e);
         }
     }
+
+    /**
+     * Text, bytes or a stream, which hold Json as text.
+     */
+    private static boolean isText(Object body) {
+        return body instanceof String || body instanceof byte[] || body 
instanceof InputStream || body instanceof Reader;
+    }
 }
diff --git 
a/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/transform/JsonPojoDataTypeTransformer.java
 
b/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/transform/JsonPojoDataTypeTransformer.java
index f423cd395b61..2c23d1cc812f 100644
--- 
a/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/transform/JsonPojoDataTypeTransformer.java
+++ 
b/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/transform/JsonPojoDataTypeTransformer.java
@@ -75,7 +75,7 @@ public class JsonPojoDataTypeTransformer extends Transformer 
implements CamelCon
             message.setHeader(Exchange.CONTENT_TYPE, 
MimeType.JAVA_OBJECT.type());
 
             Class<?> contentType = 
camelContext.getClassResolver().resolveMandatoryClass(contentClass);
-            if (contentType.isAssignableFrom(message.getBody().getClass())) {
+            if (contentType.isInstance(message.getBody())) {
                 return;
             }
 
diff --git 
a/components/camel-jackson/src/test/java/org/apache/camel/component/jackson/transform/JsonDataTypeTransformerTest.java
 
b/components/camel-jackson/src/test/java/org/apache/camel/component/jackson/transform/JsonDataTypeTransformerTest.java
index fa0f4ee7d234..0acae6cfd382 100644
--- 
a/components/camel-jackson/src/test/java/org/apache/camel/component/jackson/transform/JsonDataTypeTransformerTest.java
+++ 
b/components/camel-jackson/src/test/java/org/apache/camel/component/jackson/transform/JsonDataTypeTransformerTest.java
@@ -17,7 +17,11 @@
 
 package org.apache.camel.component.jackson.transform;
 
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -25,6 +29,7 @@ import com.fasterxml.jackson.databind.JsonNode;
 import org.apache.camel.CamelExecutionException;
 import org.apache.camel.Exchange;
 import org.apache.camel.component.jackson.SchemaHelper;
+import org.apache.camel.converter.stream.InputStreamCache;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.spi.BodyType.Carrier;
 import org.apache.camel.spi.BodyTypes;
@@ -103,26 +108,134 @@ class JsonDataTypeTransformerTest {
         Assertions.assertEquals(JsonDataTypeTransformer.class, 
transformer.getClass());
     }
 
+    @Test
+    void shouldHandleMapAndList() throws Exception {
+        // CAMEL-26300: a Map or a List has no class of its own, and is 
written as a Json object or array
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put("name", "Goofy");
+        map.put("age", 25);
+        Exchange exchange = new DefaultExchange(camelContext);
+        exchange.getMessage().setBody(map);
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        JSONAssert.assertEquals("""
+                    {"name":"Goofy","age":25}
+                """, exchange.getMessage().getBody(String.class), true);
+
+        exchange = new DefaultExchange(camelContext);
+        exchange.getMessage().setBody(List.of(new Person("Goofy", 25), 
Map.of("name", "Mickey")));
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        JSONAssert.assertEquals("""
+                    [{"name":"Goofy","age":25},{"name":"Mickey"}]
+                """, exchange.getMessage().getBody(String.class), true);
+    }
+
+    @Test
+    void shouldHandleJsonAsBytesOrStream() throws Exception {
+        // CAMEL-26300: Json as bytes, a stream, a reader or the stream cache 
is kept as it is
+        String json = "{ \"name\": \"Goofy\", \"age\": 25 }";
+        byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
+        for (Object body : List.of(bytes, new ByteArrayInputStream(bytes), new 
StringReader(json),
+                new InputStreamCache(bytes))) {
+            Exchange exchange = new DefaultExchange(camelContext);
+            exchange.getMessage().setBody(body);
+            transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+            Assertions.assertInstanceOf(byte[].class, 
exchange.getMessage().getBody(), body.getClass().getName());
+            Assertions.assertEquals(json, 
exchange.getMessage().getBody(String.class), body.getClass().getName());
+        }
+    }
+
+    @Test
+    void shouldWriteOtherTextAsJsonString() throws Exception {
+        // CAMEL-26300: text that is no Json object or array, as a String or 
as bytes, becomes a Json string
+        String text = "Hello \"Goofy\"";
+        for (Object body : List.of(text, 
text.getBytes(StandardCharsets.UTF_8))) {
+            Exchange exchange = new DefaultExchange(camelContext);
+            exchange.getMessage().setBody(body);
+            transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+            Assertions.assertEquals("\"Hello \\\"Goofy\\\"\"", 
exchange.getMessage().getBody(String.class),
+                    body.getClass().getName());
+            Assertions.assertEquals(text, 
Json.mapper().readTree(exchange.getMessage().getBody(byte[].class)).asText());
+        }
+    }
+
+    @Test
+    void shouldWriteJsonScalarTextAsJsonString() throws Exception {
+        // CAMEL-26300: only a Json object or array is kept as Json text, so a 
Json number, boolean, null or quoted
+        // string given as text becomes a Json string
+        Map<String, String> expected = new LinkedHashMap<>();
+        expected.put("42", "\"42\"");
+        expected.put("true", "\"true\"");
+        expected.put("null", "\"null\"");
+        expected.put("\"Hello\"", "\"\\\"Hello\\\"\"");
+        for (Map.Entry<String, String> entry : expected.entrySet()) {
+            Exchange exchange = new DefaultExchange(camelContext);
+            exchange.getMessage().setBody(entry.getKey());
+            transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+            Assertions.assertEquals(entry.getValue(), 
exchange.getMessage().getBody(String.class), entry.getKey());
+            Assertions.assertEquals(entry.getKey(),
+                    
Json.mapper().readTree(exchange.getMessage().getBody(byte[].class)).asText());
+        }
+    }
+
+    @Test
+    void shouldReadBytesWithTheExchangeCharset() throws Exception {
+        // CAMEL-26300: bytes are read as text with the charset of the 
exchange, and the Json is written in UTF-8
+        String json = "{\"name\":\"Jos\u00e9\"}";
+        Exchange exchange = new DefaultExchange(camelContext);
+        exchange.setProperty(Exchange.CHARSET_NAME, 
StandardCharsets.ISO_8859_1.name());
+        
exchange.getMessage().setBody(json.getBytes(StandardCharsets.ISO_8859_1));
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        Assertions.assertArrayEquals(json.getBytes(StandardCharsets.UTF_8), 
exchange.getMessage().getBody(byte[].class));
+
+        exchange = new DefaultExchange(camelContext);
+        exchange.setProperty(Exchange.CHARSET_NAME, 
StandardCharsets.ISO_8859_1.name());
+        
exchange.getMessage().setBody("caf\u00e9".getBytes(StandardCharsets.ISO_8859_1));
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        
Assertions.assertArrayEquals("\"caf\u00e9\"".getBytes(StandardCharsets.UTF_8),
+                exchange.getMessage().getBody(byte[].class));
+    }
+
+    @Test
+    void shouldWriteBytesInBase64WithTheByteArrayContentClass() throws 
Exception {
+        // CAMEL-26300: a payload that is not text can be given the content 
class byte[], which Jackson writes in Base64
+        Exchange exchange = new DefaultExchange(camelContext);
+        exchange.setProperty(SchemaHelper.CONTENT_CLASS, "byte[]");
+        exchange.getMessage().setBody(new byte[] { 0, 1, 2, (byte) 0xFF });
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        Assertions.assertEquals("\"AAEC/w==\"", 
exchange.getMessage().getBody(String.class));
+    }
+
     @Test
     void theBodyTypesSayTheBody() throws Exception {
-        // CAMEL-25928: Json text, a JsonNode, a POJO or a null body, as 
transformerIn says, and the Json bytes
-        // transformerOut says
+        // CAMEL-25928: Json as text, bytes or a stream, other text, a Map, a 
List, a JsonNode, a POJO or a null body,
+        // as transformerIn says, and the Json bytes transformerOut says
         BodyTypes bodyTypes = 
JsonDataTypeTransformer.class.getAnnotation(BodyTypes.class);
-        Assertions.assertEquals(List.of(Carrier.TEXT, Carrier.POJO, 
Carrier.NULL),
+        Assertions.assertEquals(
+                List.of(Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, 
Carrier.MAP, Carrier.LIST, Carrier.POJO, Carrier.NULL),
                 List.of(bodyTypes.transformerIn().value()));
         Assertions.assertEquals(List.of(Carrier.BYTES), 
List.of(bodyTypes.transformerOut().value()));
         Assertions.assertEquals(byte[].class.getCanonicalName(), 
bodyTypes.transformerOut().javaType());
         Assertions.assertEquals("json", bodyTypes.transformerOut().format());
         String json = "{ \"name\": \"Goofy\", \"age\": 25 }";
-        for (Object body : Arrays.asList(json, 
Json.mapper().readerFor(JsonNode.class).readValue(json), new Person("Goofy", 
25),
-                null)) {
+        byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
+        for (Object body : Arrays.asList(json, bytes, new 
ByteArrayInputStream(bytes), "Goofy", Map.of("name", "Goofy"),
+                List.of("Goofy"), 
Json.mapper().readerFor(JsonNode.class).readValue(json), new Person("Goofy", 
25), null)) {
             Exchange exchange = new DefaultExchange(camelContext);
             exchange.getMessage().setBody(body);
             transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
             Assertions.assertInstanceOf(byte[].class, 
exchange.getMessage().getBody(), String.valueOf(body));
         }
-        // a Map is no JsonNode, the class written without the X-Content-Class 
property
+        // with the X-Content-Class property only a body of that class
         Exchange other = new DefaultExchange(camelContext);
+        other.setProperty(SchemaHelper.CONTENT_CLASS, Person.class.getName());
         other.getMessage().setBody(Map.of("name", "Goofy"));
         Assertions.assertThrows(CamelExecutionException.class,
                 () -> transformer.transform(other.getMessage(), DataType.ANY, 
DataType.ANY));
diff --git 
a/components/camel-jackson/src/test/java/org/apache/camel/component/jackson/transform/JsonPojoDataTypeTransformerTest.java
 
b/components/camel-jackson/src/test/java/org/apache/camel/component/jackson/transform/JsonPojoDataTypeTransformerTest.java
index 3bd36d0c1de4..dc0db78e868f 100644
--- 
a/components/camel-jackson/src/test/java/org/apache/camel/component/jackson/transform/JsonPojoDataTypeTransformerTest.java
+++ 
b/components/camel-jackson/src/test/java/org/apache/camel/component/jackson/transform/JsonPojoDataTypeTransformerTest.java
@@ -28,6 +28,7 @@ import java.util.Map;
 import com.fasterxml.jackson.databind.JsonNode;
 import org.apache.camel.CamelExecutionException;
 import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.component.jackson.SchemaHelper;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.spi.BodyType.Carrier;
@@ -124,6 +125,19 @@ class JsonPojoDataTypeTransformerTest {
         Assertions.assertEquals(19, 
exchange.getMessage().getBody(Person.class).age());
     }
 
+    @Test
+    void shouldFailOnNullBody() {
+        // CAMEL-26300: a null body has no Json to read, which fails as other 
bodies without Json do
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
+        exchange.getMessage().setBody(null);
+
+        CamelExecutionException e = 
Assertions.assertThrows(CamelExecutionException.class,
+                () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
+        Assertions.assertInstanceOf(InvalidPayloadException.class, 
e.getCause());
+    }
+
     @Test
     public void shouldLookupDataTypeTransformer() throws Exception {
         Transformer transformer = camelContext.getTransformerRegistry()
diff --git 
a/components/camel-jackson3-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-java-object.json
 
b/components/camel-jackson3-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-java-object.json
index f91a8856e8d5..0d488b5eaa92 100644
--- 
a/components/camel-jackson3-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-java-object.json
+++ 
b/components/camel-jackson3-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-java-object.json
@@ -19,7 +19,7 @@
         "file",
         "pojo"
       ],
-      "description": "Json text, or Avro binary with the Avro schema in the 
X-Content-Schema exchange property, read into the class of the X-Content-Class 
exchange property, which a body other than a POJO needs: a POJO of that class, 
or any POJO without it, is kept, and a Map or a null body fail"
+      "description": "Json text or a JsonNode, or Avro binary with the Avro 
schema in the X-Content-Schema exchange property, read into the class of the 
X-Content-Class exchange property, which a body other than a POJO needs: a POJO 
of that class, or any POJO without it, is kept, and a Map or a null body fail"
     },
     "transformerOut": {
       "carriers": [
diff --git 
a/components/camel-jackson3-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-struct.json
 
b/components/camel-jackson3-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-struct.json
index 6c31d85e72e3..c834924de3cf 100644
--- 
a/components/camel-jackson3-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-struct.json
+++ 
b/components/camel-jackson3-avro/src/generated/resources/META-INF/services/org/apache/camel/transformer/avro-x-struct.json
@@ -13,12 +13,13 @@
   "bodyTypes": {
     "transformerIn": {
       "carriers": [
+        "text",
         "bytes",
         "stream",
         "file",
         "pojo"
       ],
-      "description": "Needs the Avro schema in the X-Content-Schema exchange 
property: Avro binary, a JsonNode or a POJO; Json text, a Map or a null body 
fail"
+      "description": "Needs the Avro schema in the X-Content-Schema exchange 
property: a Json object or array as text, Avro binary, a JsonNode or a POJO; a 
Map or a null body fail"
     },
     "transformerOut": {
       "carriers": [
diff --git 
a/components/camel-jackson3-avro/src/main/java/org/apache/camel/component/jackson3/avro/transform/AvroBinaryDataTypeTransformer.java
 
b/components/camel-jackson3-avro/src/main/java/org/apache/camel/component/jackson3/avro/transform/AvroBinaryDataTypeTransformer.java
index 69de1c8099fa..3c1875a1c814 100644
--- 
a/components/camel-jackson3-avro/src/main/java/org/apache/camel/component/jackson3/avro/transform/AvroBinaryDataTypeTransformer.java
+++ 
b/components/camel-jackson3-avro/src/main/java/org/apache/camel/component/jackson3/avro/transform/AvroBinaryDataTypeTransformer.java
@@ -34,6 +34,7 @@ import org.apache.camel.spi.DataType;
 import org.apache.camel.spi.DataTypeTransformer;
 import org.apache.camel.spi.MimeType;
 import org.apache.camel.spi.Transformer;
+import tools.jackson.core.JacksonException;
 import tools.jackson.databind.JsonNode;
 import tools.jackson.dataformat.avro.AvroSchema;
 
@@ -77,7 +78,7 @@ public class AvroBinaryDataTypeTransformer extends 
Transformer {
 
             message.setHeader(Exchange.CONTENT_TYPE, 
MimeType.AVRO_BINARY.type());
             message.setHeader(SchemaHelper.CONTENT_SCHEMA, 
schema.getAvroSchema().getFullName());
-        } catch (InvalidPayloadException | IOException | 
ClassNotFoundException e) {
+        } catch (InvalidPayloadException | IOException | JacksonException | 
ClassNotFoundException e) {
             throw new CamelExecutionException("Failed to apply Avro binary 
data type on exchange", message.getExchange(), e);
         }
     }
diff --git 
a/components/camel-jackson3-avro/src/main/java/org/apache/camel/component/jackson3/avro/transform/AvroPojoDataTypeTransformer.java
 
b/components/camel-jackson3-avro/src/main/java/org/apache/camel/component/jackson3/avro/transform/AvroPojoDataTypeTransformer.java
index 7d17434b2203..e754ed5fbfcd 100644
--- 
a/components/camel-jackson3-avro/src/main/java/org/apache/camel/component/jackson3/avro/transform/AvroPojoDataTypeTransformer.java
+++ 
b/components/camel-jackson3-avro/src/main/java/org/apache/camel/component/jackson3/avro/transform/AvroPojoDataTypeTransformer.java
@@ -39,10 +39,11 @@ import tools.jackson.databind.JsonNode;
 @DataTypeTransformer(name = "avro-x-java-object",
                      description = "Transforms from JSon to Java object using 
Jackson Avro (supports content schema)")
 @BodyTypes(transformerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.POJO },
-                                     description = "Json text, or Avro binary 
with the Avro schema in the X-Content-Schema"
-                                                   + " exchange property, read 
into the class of the X-Content-Class exchange"
-                                                   + " property, which a body 
other than a POJO needs: a POJO of that class,"
-                                                   + " or any POJO without it, 
is kept, and a Map or a null body fail"),
+                                     description = "Json text or a JsonNode, 
or Avro binary with the Avro schema in the"
+                                                   + " X-Content-Schema 
exchange property, read into the class of the"
+                                                   + " X-Content-Class 
exchange property, which a body other than a POJO"
+                                                   + " needs: a POJO of that 
class, or any POJO without it, is kept, and a"
+                                                   + " Map or a null body 
fail"),
            transformerOut = @BodyType(value = Carrier.UNKNOWN,
                                       description = "An object of the class of 
the X-Content-Class exchange property"))
 public class AvroPojoDataTypeTransformer extends JsonPojoDataTypeTransformer {
diff --git 
a/components/camel-jackson3-avro/src/main/java/org/apache/camel/component/jackson3/avro/transform/AvroStructDataTypeTransformer.java
 
b/components/camel-jackson3-avro/src/main/java/org/apache/camel/component/jackson3/avro/transform/AvroStructDataTypeTransformer.java
index cf9b6403abc0..db3b15bf250f 100644
--- 
a/components/camel-jackson3-avro/src/main/java/org/apache/camel/component/jackson3/avro/transform/AvroStructDataTypeTransformer.java
+++ 
b/components/camel-jackson3-avro/src/main/java/org/apache/camel/component/jackson3/avro/transform/AvroStructDataTypeTransformer.java
@@ -24,6 +24,7 @@ import org.apache.camel.Exchange;
 import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.Message;
 import org.apache.camel.component.jackson3.SchemaHelper;
+import org.apache.camel.component.jackson3.transform.Json;
 import org.apache.camel.spi.BodyType;
 import org.apache.camel.spi.BodyType.Carrier;
 import org.apache.camel.spi.BodyTypes;
@@ -31,6 +32,7 @@ import org.apache.camel.spi.DataType;
 import org.apache.camel.spi.DataTypeTransformer;
 import org.apache.camel.spi.MimeType;
 import org.apache.camel.spi.Transformer;
+import tools.jackson.core.JacksonException;
 import tools.jackson.databind.JsonNode;
 import tools.jackson.dataformat.avro.AvroSchema;
 
@@ -40,9 +42,10 @@ import tools.jackson.dataformat.avro.AvroSchema;
  */
 @DataTypeTransformer(name = "avro-x-struct",
                      description = "Transforms to generic JSonNode using 
Jackson Avro (supports content schema)")
-@BodyTypes(transformerIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, 
Carrier.FILE, Carrier.POJO },
-                                     description = "Needs the Avro schema in 
the X-Content-Schema exchange property: Avro"
-                                                   + " binary, a JsonNode or a 
POJO; Json text, a Map or a null body fail"),
+@BodyTypes(transformerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.POJO },
+                                     description = "Needs the Avro schema in 
the X-Content-Schema exchange property: a Json"
+                                                   + " object or array as 
text, Avro binary, a JsonNode or a POJO; a Map or a"
+                                                   + " null body fail"),
            transformerOut = @BodyType(value = Carrier.POJO, javaType = 
"tools.jackson.databind.JsonNode"))
 public class AvroStructDataTypeTransformer extends Transformer {
 
@@ -62,6 +65,8 @@ public class AvroStructDataTypeTransformer extends 
Transformer {
                         = 
message.getExchange().getContext().getClassResolver().resolveMandatoryClass(contentClass);
                 unmarshalled = 
Avro.mapper().reader().forType(JsonNode.class).with(schema)
                         
.readValue(Avro.mapper().writerFor(contentType).with(schema).writeValueAsBytes(message.getBody()));
+            } else if (message.getBody() instanceof String jsonString && 
Json.isJson(jsonString)) {
+                unmarshalled = Json.mapper().readTree(jsonString);
             } else {
                 unmarshalled = 
Avro.mapper().reader().forType(JsonNode.class).with(schema).readValue(getBodyAsStream(message));
             }
@@ -69,7 +74,7 @@ public class AvroStructDataTypeTransformer extends 
Transformer {
             message.setBody(unmarshalled);
 
             message.setHeader(Exchange.CONTENT_TYPE, MimeType.STRUCT.type());
-        } catch (InvalidPayloadException | ClassNotFoundException e) {
+        } catch (InvalidPayloadException | JacksonException | 
ClassNotFoundException e) {
             throw new CamelExecutionException("Failed to apply Avro x-struct 
data type on exchange", message.getExchange(), e);
         }
     }
diff --git 
a/components/camel-jackson3-avro/src/test/java/org/apache/camel/component/jackson3/avro/transform/AvroBinaryDataTypeTransformerTest.java
 
b/components/camel-jackson3-avro/src/test/java/org/apache/camel/component/jackson3/avro/transform/AvroBinaryDataTypeTransformerTest.java
index db1d56326507..c4ce9568fdf5 100644
--- 
a/components/camel-jackson3-avro/src/test/java/org/apache/camel/component/jackson3/avro/transform/AvroBinaryDataTypeTransformerTest.java
+++ 
b/components/camel-jackson3-avro/src/test/java/org/apache/camel/component/jackson3/avro/transform/AvroBinaryDataTypeTransformerTest.java
@@ -118,6 +118,18 @@ class AvroBinaryDataTypeTransformerTest {
                 
Avro.mapper().reader().with(avroSchema).readTree(exchange.getMessage().getBody(byte[].class))),
 true);
     }
 
+    @Test
+    void shouldWrapMalformedJsonInCamelExecutionException() throws Exception {
+        // CAMEL-26300: the JacksonException of Jackson 3 is wrapped, as the 
errors of Jackson 2 are
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.getMessage().setBody("{ this is no json }");
+
+        Assertions.assertThrows(CamelExecutionException.class,
+                () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
+    }
+
     @Test
     public void shouldLookupDataTypeTransformer() throws Exception {
         Transformer transformer = camelContext.getTransformerRegistry()
diff --git 
a/components/camel-jackson3-avro/src/test/java/org/apache/camel/component/jackson3/avro/transform/AvroPojoDataTypeTransformerTest.java
 
b/components/camel-jackson3-avro/src/test/java/org/apache/camel/component/jackson3/avro/transform/AvroPojoDataTypeTransformerTest.java
index ef41b4042a8a..78e268f22c5b 100644
--- 
a/components/camel-jackson3-avro/src/test/java/org/apache/camel/component/jackson3/avro/transform/AvroPojoDataTypeTransformerTest.java
+++ 
b/components/camel-jackson3-avro/src/test/java/org/apache/camel/component/jackson3/avro/transform/AvroPojoDataTypeTransformerTest.java
@@ -29,6 +29,7 @@ import org.apache.avro.NameValidator;
 import org.apache.avro.Schema;
 import org.apache.camel.CamelExecutionException;
 import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.component.jackson3.SchemaHelper;
 import org.apache.camel.component.jackson3.transform.Json;
 import org.apache.camel.impl.DefaultCamelContext;
@@ -136,6 +137,35 @@ class AvroPojoDataTypeTransformerTest {
         Assertions.assertEquals(19, 
exchange.getMessage().getBody(Person.class).age());
     }
 
+    @Test
+    void shouldHandleJsonNode() throws Exception {
+        // CAMEL-26300: a JsonNode is read into the class of the 
X-Content-Class property, with the Avro schema set
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
+        
exchange.getMessage().setBody(Json.mapper().readerFor(JsonNode.class).readValue("""
+                    { "name": "Goofy", "age": 25 }
+                """));
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        Assertions.assertEquals(new Person("Goofy", 25), 
exchange.getMessage().getBody());
+    }
+
+    @Test
+    void shouldFailOnNullBody() throws Exception {
+        // CAMEL-26300: a null body has no Avro binary to read, which fails as 
other bodies without it do
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
+        exchange.getMessage().setBody(null);
+
+        CamelExecutionException e = 
Assertions.assertThrows(CamelExecutionException.class,
+                () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
+        Assertions.assertInstanceOf(InvalidPayloadException.class, 
e.getCause());
+    }
+
     @Test
     public void shouldLookupDataTypeTransformer() throws Exception {
         Transformer transformer = camelContext.getTransformerRegistry()
@@ -152,8 +182,8 @@ class AvroPojoDataTypeTransformerTest {
 
     @Test
     void theBodyTypesSayTheBody(@TempDir Path dir) throws Exception {
-        // CAMEL-25928: Json text, or Avro binary as bytes, a stream or a 
file, as transformerIn says, read into the
-        // class of the X-Content-Class property, which transformerOut leaves 
unknown
+        // CAMEL-25928: Json text or a JsonNode, or Avro binary as bytes, a 
stream or a file, as transformerIn
+        // says, read into the class of the X-Content-Class property, which 
transformerOut leaves unknown
         BodyTypes bodyTypes = 
AvroPojoDataTypeTransformer.class.getAnnotation(BodyTypes.class);
         Assertions.assertEquals(List.of(Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.POJO),
                 List.of(bodyTypes.transformerIn().value()));
@@ -161,7 +191,8 @@ class AvroPojoDataTypeTransformerTest {
         String json = "{ \"name\": \"Goofy\", \"age\": 25 }";
         byte[] binary = 
Avro.mapper().writer(getSchema()).writeValueAsBytes(new Person("Goofy", 25));
         Path file = Files.write(dir.resolve("person.bin"), binary);
-        for (Object body : Arrays.asList(json, binary, new 
ByteArrayInputStream(binary), file.toFile())) {
+        for (Object body : Arrays.asList(json, binary, new 
ByteArrayInputStream(binary), file.toFile(),
+                Json.mapper().readerFor(JsonNode.class).readValue(json))) {
             Exchange exchange = new DefaultExchange(camelContext);
             exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
             exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
diff --git 
a/components/camel-jackson3-avro/src/test/java/org/apache/camel/component/jackson3/avro/transform/AvroStructDataTypeTransformerTest.java
 
b/components/camel-jackson3-avro/src/test/java/org/apache/camel/component/jackson3/avro/transform/AvroStructDataTypeTransformerTest.java
index 5f01dec19e16..102fc907d5d1 100644
--- 
a/components/camel-jackson3-avro/src/test/java/org/apache/camel/component/jackson3/avro/transform/AvroStructDataTypeTransformerTest.java
+++ 
b/components/camel-jackson3-avro/src/test/java/org/apache/camel/component/jackson3/avro/transform/AvroStructDataTypeTransformerTest.java
@@ -19,6 +19,7 @@ package org.apache.camel.component.jackson3.avro.transform;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Arrays;
@@ -68,19 +69,47 @@ class AvroStructDataTypeTransformerTest {
 
     @Test
     void shouldHandleJsonString() throws Exception {
+        // CAMEL-26300: Json text is read as Json, not as Avro binary
         Exchange exchange = new DefaultExchange(camelContext);
 
         AvroSchema avroSchema = getSchema();
         exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, avroSchema);
-        Person person = Json.mapper().readValue("""
+        exchange.getMessage().setBody("""
                     { "name": "Christoph", "age": 32 }
-                """, Person.class);
-        exchange.getMessage().setBody(AvroMapper.builder()
-                
.disable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS).build()
-                .writer(avroSchema).writeValueAsBytes(person));
+                """);
         transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
 
         Assertions.assertEquals(ObjectNode.class, 
exchange.getMessage().getBody().getClass());
+        JsonNode body = exchange.getMessage().getBody(JsonNode.class);
+        Assertions.assertEquals("Christoph", body.get("name").asString());
+        Assertions.assertEquals(32, body.get("age").asInt());
+    }
+
+    @Test
+    void shouldWrapMalformedJsonInCamelExecutionException() throws Exception {
+        // CAMEL-26300: the JacksonException of Jackson 3 is wrapped, as the 
errors of Jackson 2 are
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.getMessage().setBody("{ this is no json }");
+
+        Assertions.assertThrows(CamelExecutionException.class,
+                () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
+    }
+
+    @Test
+    void shouldReadJsonStringWhateverTheExchangeCharset() throws Exception {
+        // CAMEL-26300: Json text is read as the String it is, so a non-ASCII 
character works with any exchange charset
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.setProperty(Exchange.CHARSET_NAME, 
StandardCharsets.ISO_8859_1.name());
+        exchange.getMessage().setBody("{ \"name\": \"Jos\u00e9\", \"age\": 32 
}");
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        JsonNode body = exchange.getMessage().getBody(JsonNode.class);
+        Assertions.assertEquals("Jos\u00e9", body.get("name").asString());
+        Assertions.assertEquals(32, body.get("age").asInt());
     }
 
     @Test
@@ -138,17 +167,17 @@ class AvroStructDataTypeTransformerTest {
 
     @Test
     void theBodyTypesSayTheBody(@TempDir Path dir) throws Exception {
-        // CAMEL-25928: Avro binary as bytes, a stream or a file, a POJO or a 
JsonNode, as transformerIn says, and
-        // the JsonNode transformerOut says
+        // CAMEL-25928: Json text, Avro binary as bytes, a stream or a file, a 
POJO or a JsonNode, as transformerIn
+        // says, and the JsonNode transformerOut says
         BodyTypes bodyTypes = 
AvroStructDataTypeTransformer.class.getAnnotation(BodyTypes.class);
-        Assertions.assertEquals(List.of(Carrier.BYTES, Carrier.STREAM, 
Carrier.FILE, Carrier.POJO),
+        Assertions.assertEquals(List.of(Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.POJO),
                 List.of(bodyTypes.transformerIn().value()));
         Assertions.assertEquals(List.of(Carrier.POJO), 
List.of(bodyTypes.transformerOut().value()));
         Assertions.assertEquals(JsonNode.class.getName(), 
bodyTypes.transformerOut().javaType());
         String json = "{ \"name\": \"Goofy\", \"age\": 25 }";
         byte[] binary = 
Avro.mapper().writer(getSchema()).writeValueAsBytes(new Person("Goofy", 25));
         Path file = Files.write(dir.resolve("person.bin"), binary);
-        for (Object body : Arrays.asList(binary, new 
ByteArrayInputStream(binary), file.toFile(), new Person("Goofy", 25),
+        for (Object body : Arrays.asList(json, binary, new 
ByteArrayInputStream(binary), file.toFile(), new Person("Goofy", 25),
                 Json.mapper().readerFor(JsonNode.class).readValue(json))) {
             Exchange exchange = new DefaultExchange(camelContext);
             exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
@@ -162,11 +191,5 @@ class AvroStructDataTypeTransformerTest {
         other.getMessage().setBody(Map.of("name", "Goofy"));
         Assertions.assertThrows(CamelExecutionException.class,
                 () -> transformer.transform(other.getMessage(), DataType.ANY, 
DataType.ANY));
-        // nor is Json text
-        Exchange text = new DefaultExchange(camelContext);
-        text.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
-        text.getMessage().setBody(json);
-        Assertions.assertThrows(RuntimeException.class,
-                () -> transformer.transform(text.getMessage(), DataType.ANY, 
DataType.ANY));
     }
 }
diff --git 
a/components/camel-jackson3-protobuf/src/generated/resources/META-INF/services/org/apache/camel/transformer/protobuf-x-java-object.json
 
b/components/camel-jackson3-protobuf/src/generated/resources/META-INF/services/org/apache/camel/transformer/protobuf-x-java-object.json
index 96e39da0c2e0..ab1b1270e99f 100644
--- 
a/components/camel-jackson3-protobuf/src/generated/resources/META-INF/services/org/apache/camel/transformer/protobuf-x-java-object.json
+++ 
b/components/camel-jackson3-protobuf/src/generated/resources/META-INF/services/org/apache/camel/transformer/protobuf-x-java-object.json
@@ -19,7 +19,7 @@
         "file",
         "pojo"
       ],
-      "description": "Json text, or Protobuf binary with the Protobuf schema 
in the X-Content-Schema exchange property, read into the class of the 
X-Content-Class exchange property, which a body other than a POJO needs: a POJO 
of that class, or any POJO without it, is kept, and a Map or a null body fail"
+      "description": "Json text or a JsonNode, or Protobuf binary with the 
Protobuf schema in the X-Content-Schema exchange property, read into the class 
of the X-Content-Class exchange property, which a body other than a POJO needs: 
a POJO of that class, or any POJO without it, is kept, and a Map or a null body 
fail"
     },
     "transformerOut": {
       "carriers": [
diff --git 
a/components/camel-jackson3-protobuf/src/main/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufBinaryDataTypeTransformer.java
 
b/components/camel-jackson3-protobuf/src/main/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufBinaryDataTypeTransformer.java
index 84c7ac299ee5..400deeba15c1 100644
--- 
a/components/camel-jackson3-protobuf/src/main/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufBinaryDataTypeTransformer.java
+++ 
b/components/camel-jackson3-protobuf/src/main/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufBinaryDataTypeTransformer.java
@@ -33,6 +33,7 @@ import org.apache.camel.spi.DataType;
 import org.apache.camel.spi.DataTypeTransformer;
 import org.apache.camel.spi.MimeType;
 import org.apache.camel.spi.Transformer;
+import tools.jackson.core.JacksonException;
 import tools.jackson.databind.JsonNode;
 import tools.jackson.dataformat.protobuf.schema.ProtobufSchema;
 
@@ -76,7 +77,7 @@ public class ProtobufBinaryDataTypeTransformer extends 
Transformer {
 
             message.setHeader(Exchange.CONTENT_TYPE, 
MimeType.PROTOBUF_BINARY.type());
             message.setHeader(SchemaHelper.CONTENT_SCHEMA, 
schema.getSource().toString());
-        } catch (InvalidPayloadException | IOException | 
ClassNotFoundException e) {
+        } catch (InvalidPayloadException | IOException | JacksonException | 
ClassNotFoundException e) {
             throw new CamelExecutionException(
                     "Failed to apply Protobuf binary data type on exchange", 
message.getExchange(), e);
         }
diff --git 
a/components/camel-jackson3-protobuf/src/main/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufPojoDataTypeTransformer.java
 
b/components/camel-jackson3-protobuf/src/main/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufPojoDataTypeTransformer.java
index 78842648f837..6c1409955d48 100644
--- 
a/components/camel-jackson3-protobuf/src/main/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufPojoDataTypeTransformer.java
+++ 
b/components/camel-jackson3-protobuf/src/main/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufPojoDataTypeTransformer.java
@@ -39,8 +39,8 @@ import tools.jackson.databind.JsonNode;
 @DataTypeTransformer(name = "protobuf-x-java-object",
                      description = "Transforms from JSon to Java object using 
Jackson Protobuf (supports content schema)")
 @BodyTypes(transformerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.POJO },
-                                     description = "Json text, or Protobuf 
binary with the Protobuf schema in the"
-                                                   + " X-Content-Schema 
exchange property, read into the class of the"
+                                     description = "Json text or a JsonNode, 
or Protobuf binary with the Protobuf schema"
+                                                   + " in the X-Content-Schema 
exchange property, read into the class of the"
                                                    + " X-Content-Class 
exchange property, which a body other than a POJO"
                                                    + " needs: a POJO of that 
class, or any POJO without it, is kept, and a"
                                                    + " Map or a null body 
fail"),
diff --git 
a/components/camel-jackson3-protobuf/src/main/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufStructDataTypeTransformer.java
 
b/components/camel-jackson3-protobuf/src/main/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufStructDataTypeTransformer.java
index 88cb18321a67..4d23fd053b81 100644
--- 
a/components/camel-jackson3-protobuf/src/main/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufStructDataTypeTransformer.java
+++ 
b/components/camel-jackson3-protobuf/src/main/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufStructDataTypeTransformer.java
@@ -32,6 +32,7 @@ import org.apache.camel.spi.DataType;
 import org.apache.camel.spi.DataTypeTransformer;
 import org.apache.camel.spi.MimeType;
 import org.apache.camel.spi.Transformer;
+import tools.jackson.core.JacksonException;
 import tools.jackson.databind.JsonNode;
 import tools.jackson.dataformat.protobuf.schema.ProtobufSchema;
 
@@ -65,7 +66,7 @@ public class ProtobufStructDataTypeTransformer extends 
Transformer {
                 unmarshalled = 
Protobuf.mapper().reader().forType(JsonNode.class).with(schema)
                         
.readValue(Protobuf.mapper().writerFor(contentType).with(schema).writeValueAsBytes(message.getBody()));
             } else if (message.getBody() instanceof String jsonString && 
Json.isJson(jsonString)) {
-                unmarshalled = 
Json.mapper().readTree(getBodyAsStream(message));
+                unmarshalled = Json.mapper().readTree(jsonString);
             } else {
                 unmarshalled
                         = 
Protobuf.mapper().reader().forType(JsonNode.class).with(schema).readValue(getBodyAsStream(message));
@@ -74,7 +75,7 @@ public class ProtobufStructDataTypeTransformer extends 
Transformer {
             message.setBody(unmarshalled);
 
             message.setHeader(Exchange.CONTENT_TYPE, MimeType.STRUCT.type());
-        } catch (InvalidPayloadException | ClassNotFoundException e) {
+        } catch (InvalidPayloadException | JacksonException | 
ClassNotFoundException e) {
             throw new CamelExecutionException(
                     "Failed to apply Protobuf x-struct data type on exchange", 
message.getExchange(), e);
         }
diff --git 
a/components/camel-jackson3-protobuf/src/test/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufBinaryDataTypeTransformerTest.java
 
b/components/camel-jackson3-protobuf/src/test/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufBinaryDataTypeTransformerTest.java
index c9f26c9a4169..56f87be5718c 100644
--- 
a/components/camel-jackson3-protobuf/src/test/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufBinaryDataTypeTransformerTest.java
+++ 
b/components/camel-jackson3-protobuf/src/test/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufBinaryDataTypeTransformerTest.java
@@ -116,6 +116,18 @@ class ProtobufBinaryDataTypeTransformerTest {
                 
Protobuf.mapper().reader().with(protobufSchema).readTree(exchange.getMessage().getBody(byte[].class))),
 true);
     }
 
+    @Test
+    void shouldWrapMalformedJsonInCamelExecutionException() throws Exception {
+        // CAMEL-26300: the JacksonException of Jackson 3 is wrapped, as the 
errors of Jackson 2 are
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.getMessage().setBody("{ this is no json }");
+
+        Assertions.assertThrows(CamelExecutionException.class,
+                () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
+    }
+
     @Test
     public void shouldLookupDataTypeTransformer() throws Exception {
         Transformer transformer = camelContext.getTransformerRegistry()
diff --git 
a/components/camel-jackson3-protobuf/src/test/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufPojoDataTypeTransformerTest.java
 
b/components/camel-jackson3-protobuf/src/test/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufPojoDataTypeTransformerTest.java
index a8bb2721d733..ae0c3060ef4b 100644
--- 
a/components/camel-jackson3-protobuf/src/test/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufPojoDataTypeTransformerTest.java
+++ 
b/components/camel-jackson3-protobuf/src/test/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufPojoDataTypeTransformerTest.java
@@ -27,6 +27,7 @@ import java.util.Map;
 
 import org.apache.camel.CamelExecutionException;
 import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.component.jackson3.SchemaHelper;
 import org.apache.camel.component.jackson3.transform.Json;
 import org.apache.camel.impl.DefaultCamelContext;
@@ -134,6 +135,35 @@ class ProtobufPojoDataTypeTransformerTest {
         Assertions.assertEquals(19, 
exchange.getMessage().getBody(Person.class).age());
     }
 
+    @Test
+    void shouldHandleJsonNode() throws Exception {
+        // CAMEL-26300: a JsonNode is read into the class of the 
X-Content-Class property, with the Protobuf schema set
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
+        
exchange.getMessage().setBody(Json.mapper().readerFor(JsonNode.class).readValue("""
+                    { "name": "Goofy", "age": 25 }
+                """));
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        Assertions.assertEquals(new Person("Goofy", 25), 
exchange.getMessage().getBody());
+    }
+
+    @Test
+    void shouldFailOnNullBody() throws Exception {
+        // CAMEL-26300: a null body has no Protobuf binary to read, which 
fails as other bodies without it do
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
+        exchange.getMessage().setBody(null);
+
+        CamelExecutionException e = 
Assertions.assertThrows(CamelExecutionException.class,
+                () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
+        Assertions.assertInstanceOf(InvalidPayloadException.class, 
e.getCause());
+    }
+
     @Test
     public void shouldLookupDataTypeTransformer() throws Exception {
         Transformer transformer = camelContext.getTransformerRegistry()
@@ -149,8 +179,8 @@ class ProtobufPojoDataTypeTransformerTest {
 
     @Test
     void theBodyTypesSayTheBody(@TempDir Path dir) throws Exception {
-        // CAMEL-25928: Json text, or Protobuf binary as bytes, a stream or a 
file, as transformerIn says, read into the
-        // class of the X-Content-Class property, which transformerOut leaves 
unknown
+        // CAMEL-25928: Json text or a JsonNode, or Protobuf binary as bytes, 
a stream or a file, as transformerIn
+        // says, read into the class of the X-Content-Class property, which 
transformerOut leaves unknown
         BodyTypes bodyTypes = 
ProtobufPojoDataTypeTransformer.class.getAnnotation(BodyTypes.class);
         Assertions.assertEquals(List.of(Carrier.TEXT, Carrier.BYTES, 
Carrier.STREAM, Carrier.FILE, Carrier.POJO),
                 List.of(bodyTypes.transformerIn().value()));
@@ -158,7 +188,8 @@ class ProtobufPojoDataTypeTransformerTest {
         String json = "{ \"name\": \"Goofy\", \"age\": 25 }";
         byte[] binary = 
Protobuf.mapper().writer(getSchema()).writeValueAsBytes(new Person("Goofy", 
25));
         Path file = Files.write(dir.resolve("person.bin"), binary);
-        for (Object body : Arrays.asList(json, binary, new 
ByteArrayInputStream(binary), file.toFile())) {
+        for (Object body : Arrays.asList(json, binary, new 
ByteArrayInputStream(binary), file.toFile(),
+                Json.mapper().readerFor(JsonNode.class).readValue(json))) {
             Exchange exchange = new DefaultExchange(camelContext);
             exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
             exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
diff --git 
a/components/camel-jackson3-protobuf/src/test/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufStructDataTypeTransformerTest.java
 
b/components/camel-jackson3-protobuf/src/test/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufStructDataTypeTransformerTest.java
index d1ae3b1b3e13..67c10feecae9 100644
--- 
a/components/camel-jackson3-protobuf/src/test/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufStructDataTypeTransformerTest.java
+++ 
b/components/camel-jackson3-protobuf/src/test/java/org/apache/camel/component/jackson3/protobuf/transform/ProtobufStructDataTypeTransformerTest.java
@@ -19,6 +19,7 @@ package 
org.apache.camel.component.jackson3.protobuf.transform;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Arrays;
@@ -75,6 +76,21 @@ class ProtobufStructDataTypeTransformerTest {
         Assertions.assertEquals(ObjectNode.class, 
exchange.getMessage().getBody().getClass());
     }
 
+    @Test
+    void shouldReadJsonStringWhateverTheExchangeCharset() throws Exception {
+        // CAMEL-26300: Json text is read as the String it is, so a non-ASCII 
character works with any exchange charset
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.setProperty(Exchange.CHARSET_NAME, 
StandardCharsets.ISO_8859_1.name());
+        exchange.getMessage().setBody("{ \"name\": \"Jos\u00e9\", \"age\": 32 
}");
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        JsonNode body = exchange.getMessage().getBody(JsonNode.class);
+        Assertions.assertEquals("Jos\u00e9", body.get("name").asString());
+        Assertions.assertEquals(32, body.get("age").asInt());
+    }
+
     @Test
     void shouldHandlePojo() throws Exception {
         Exchange exchange = new DefaultExchange(camelContext);
@@ -114,6 +130,18 @@ class ProtobufStructDataTypeTransformerTest {
         Assertions.assertEquals(ObjectNode.class, 
exchange.getMessage().getBody().getClass());
     }
 
+    @Test
+    void shouldWrapMalformedJsonInCamelExecutionException() throws Exception {
+        // CAMEL-26300: the JacksonException of Jackson 3 is wrapped, as the 
errors of Jackson 2 are
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_SCHEMA, getSchema());
+        exchange.getMessage().setBody("{ this is no json }");
+
+        Assertions.assertThrows(CamelExecutionException.class,
+                () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
+    }
+
     @Test
     public void shouldLookupDataTypeTransformer() throws Exception {
         Transformer transformer = camelContext.getTransformerRegistry()
diff --git 
a/components/camel-jackson3/src/generated/resources/META-INF/services/org/apache/camel/transformer/application-json.json
 
b/components/camel-jackson3/src/generated/resources/META-INF/services/org/apache/camel/transformer/application-json.json
index f1142ee097ce..35a29467a7fe 100644
--- 
a/components/camel-jackson3/src/generated/resources/META-INF/services/org/apache/camel/transformer/application-json.json
+++ 
b/components/camel-jackson3/src/generated/resources/META-INF/services/org/apache/camel/transformer/application-json.json
@@ -14,10 +14,14 @@
     "transformerIn": {
       "carriers": [
         "text",
+        "bytes",
+        "stream",
+        "map",
+        "list",
         "pojo",
         "null"
       ],
-      "description": "A Json object or array as text, a JsonNode or a POJO, of 
the class of the X-Content-Class exchange property when set: other text, bytes, 
a stream, a Map or a List fail, and a null body becomes null"
+      "description": "A Json object or array as text, bytes or a stream, a 
Map, a List, a JsonNode or a POJO; other text, also a Json number, boolean, 
null or quoted string, becomes a Json string; bytes and a stream are read as 
text with the exchange charset, so a payload that is not text must be encoded 
first, such as in Base64, or given a content class; with the X-Content-Class 
exchange property only a Json object or array as text or a body of that class; 
a null body becomes null"
     },
     "transformerOut": {
       "carriers": [
diff --git 
a/components/camel-jackson3/src/main/java/org/apache/camel/component/jackson3/transform/JsonDataTypeTransformer.java
 
b/components/camel-jackson3/src/main/java/org/apache/camel/component/jackson3/transform/JsonDataTypeTransformer.java
index 62d17ccc2c5a..3518ce062ef1 100644
--- 
a/components/camel-jackson3/src/main/java/org/apache/camel/component/jackson3/transform/JsonDataTypeTransformer.java
+++ 
b/components/camel-jackson3/src/main/java/org/apache/camel/component/jackson3/transform/JsonDataTypeTransformer.java
@@ -16,10 +16,15 @@
  */
 package org.apache.camel.component.jackson3.transform;
 
+import java.io.InputStream;
+import java.io.Reader;
 import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.Map;
 
 import org.apache.camel.CamelExecutionException;
 import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.Message;
 import org.apache.camel.component.jackson3.SchemaHelper;
 import org.apache.camel.spi.BodyType;
@@ -34,14 +39,20 @@ import tools.jackson.databind.JsonNode;
 
 /**
  * Data type uses Jackson data format to marshal given Exchange payload to a 
Json (binary byte array representation).
- * Requires Exchange payload as JsonNode representation.
+ * Json text is kept, other text becomes a Json string, and a Map, a List, a 
JsonNode or a POJO is written as Json.
+ * Bytes and a stream are read as text with the charset of the exchange.
  */
 @DataTypeTransformer(name = "application-json",
                      description = "Transforms from JSon to binary (byte 
array) using Jackson 3")
-@BodyTypes(transformerIn = @BodyType(value = { Carrier.TEXT, Carrier.POJO, 
Carrier.NULL },
-                                     description = "A Json object or array as 
text, a JsonNode or a POJO, of the class of"
-                                                   + " the X-Content-Class 
exchange property when set: other text, bytes, a"
-                                                   + " stream, a Map or a List 
fail, and a null body becomes null"),
+@BodyTypes(transformerIn = @BodyType(value = {
+        Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.MAP, 
Carrier.LIST, Carrier.POJO, Carrier.NULL },
+                                     description = "A Json object or array as 
text, bytes or a stream, a Map, a List, a"
+                                                   + " JsonNode or a POJO; 
other text, also a Json number, boolean, null or"
+                                                   + " quoted string, becomes 
a Json string; bytes and a stream are read as"
+                                                   + " text with the exchange 
charset, so a payload that is not text must be"
+                                                   + " encoded first, such as 
in Base64, or given a content class; with the"
+                                                   + " X-Content-Class 
exchange property only a Json object or array as text"
+                                                   + " or a body of that 
class; a null body becomes null"),
            transformerOut = @BodyType(value = Carrier.BYTES, javaType = 
"byte[]", format = "json"))
 public class JsonDataTypeTransformer extends Transformer {
 
@@ -49,14 +60,24 @@ public class JsonDataTypeTransformer extends Transformer {
     public void transform(Message message, DataType fromType, DataType toType) 
{
         try {
             byte[] marshalled;
-            if (message.getBody() instanceof String jsonString && 
Json.isJson(jsonString)) {
+            Object body = message.getBody();
+            boolean hasContentClass = 
message.getExchange().getProperty(SchemaHelper.CONTENT_CLASS, String.class) != 
null;
+            if (body instanceof String jsonString && Json.isJson(jsonString)) {
                 marshalled = jsonString.getBytes(StandardCharsets.UTF_8);
+            } else if (!hasContentClass && (body instanceof Map || body 
instanceof Collection)) {
+                // a Map or a List has no class to write it as: it becomes a 
Json object or array
+                marshalled = Json.mapper().writeValueAsBytes(body);
+            } else if (!hasContentClass && isText(body)) {
+                // read as text with the exchange charset: a Json object or 
array is kept, and any other text, also a
+                // Json number, boolean, null or quoted string, becomes a Json 
string
+                String text = message.getMandatoryBody(String.class);
+                marshalled = Json.isJson(text) ? 
text.getBytes(StandardCharsets.UTF_8) : Json.mapper().writeValueAsBytes(text);
             } else {
                 String contentClass = 
SchemaHelper.resolveContentClass(message.getExchange(), 
JsonNode.class.getName());
                 Class<?> contentType
                         = 
message.getExchange().getContext().getClassResolver().resolveMandatoryClass(contentClass);
 
-                marshalled = 
Json.mapper().writer().forType(contentType).writeValueAsBytes(message.getBody());
+                marshalled = 
Json.mapper().writer().forType(contentType).writeValueAsBytes(body);
             }
             message.setBody(marshalled);
 
@@ -66,8 +87,15 @@ public class JsonDataTypeTransformer extends Transformer {
             if (contentSchema != null) {
                 message.setHeader(SchemaHelper.CONTENT_SCHEMA, contentSchema);
             }
-        } catch (JacksonException | ClassNotFoundException e) {
+        } catch (InvalidPayloadException | JacksonException | 
ClassNotFoundException e) {
             throw new CamelExecutionException("Failed to apply Json output 
data type on exchange", message.getExchange(), e);
         }
     }
+
+    /**
+     * Text, bytes or a stream, which hold Json as text.
+     */
+    private static boolean isText(Object body) {
+        return body instanceof String || body instanceof byte[] || body 
instanceof InputStream || body instanceof Reader;
+    }
 }
diff --git 
a/components/camel-jackson3/src/main/java/org/apache/camel/component/jackson3/transform/JsonPojoDataTypeTransformer.java
 
b/components/camel-jackson3/src/main/java/org/apache/camel/component/jackson3/transform/JsonPojoDataTypeTransformer.java
index 234364e9bbc7..5531aaa25d4e 100644
--- 
a/components/camel-jackson3/src/main/java/org/apache/camel/component/jackson3/transform/JsonPojoDataTypeTransformer.java
+++ 
b/components/camel-jackson3/src/main/java/org/apache/camel/component/jackson3/transform/JsonPojoDataTypeTransformer.java
@@ -76,7 +76,7 @@ public class JsonPojoDataTypeTransformer extends Transformer 
implements CamelCon
             message.setHeader(Exchange.CONTENT_TYPE, 
MimeType.JAVA_OBJECT.type());
 
             Class<?> contentType = 
camelContext.getClassResolver().resolveMandatoryClass(contentClass);
-            if (contentType.isAssignableFrom(message.getBody().getClass())) {
+            if (contentType.isInstance(message.getBody())) {
                 return;
             }
 
diff --git 
a/components/camel-jackson3/src/test/java/org/apache/camel/component/jackson3/transform/JsonDataTypeTransformerTest.java
 
b/components/camel-jackson3/src/test/java/org/apache/camel/component/jackson3/transform/JsonDataTypeTransformerTest.java
index eec04ffe331f..270627455b95 100644
--- 
a/components/camel-jackson3/src/test/java/org/apache/camel/component/jackson3/transform/JsonDataTypeTransformerTest.java
+++ 
b/components/camel-jackson3/src/test/java/org/apache/camel/component/jackson3/transform/JsonDataTypeTransformerTest.java
@@ -17,13 +17,18 @@
 
 package org.apache.camel.component.jackson3.transform;
 
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.camel.CamelExecutionException;
 import org.apache.camel.Exchange;
 import org.apache.camel.component.jackson3.SchemaHelper;
+import org.apache.camel.converter.stream.InputStreamCache;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.spi.BodyType.Carrier;
 import org.apache.camel.spi.BodyTypes;
@@ -103,26 +108,134 @@ class JsonDataTypeTransformerTest {
         Assertions.assertEquals(JsonDataTypeTransformer.class, 
transformer.getClass());
     }
 
+    @Test
+    void shouldHandleMapAndList() throws Exception {
+        // CAMEL-26300: a Map or a List has no class of its own, and is 
written as a Json object or array
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put("name", "Goofy");
+        map.put("age", 25);
+        Exchange exchange = new DefaultExchange(camelContext);
+        exchange.getMessage().setBody(map);
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        JSONAssert.assertEquals("""
+                    {"name":"Goofy","age":25}
+                """, exchange.getMessage().getBody(String.class), true);
+
+        exchange = new DefaultExchange(camelContext);
+        exchange.getMessage().setBody(List.of(new Person("Goofy", 25), 
Map.of("name", "Mickey")));
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        JSONAssert.assertEquals("""
+                    [{"name":"Goofy","age":25},{"name":"Mickey"}]
+                """, exchange.getMessage().getBody(String.class), true);
+    }
+
+    @Test
+    void shouldHandleJsonAsBytesOrStream() throws Exception {
+        // CAMEL-26300: Json as bytes, a stream, a reader or the stream cache 
is kept as it is
+        String json = "{ \"name\": \"Goofy\", \"age\": 25 }";
+        byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
+        for (Object body : List.of(bytes, new ByteArrayInputStream(bytes), new 
StringReader(json),
+                new InputStreamCache(bytes))) {
+            Exchange exchange = new DefaultExchange(camelContext);
+            exchange.getMessage().setBody(body);
+            transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+            Assertions.assertInstanceOf(byte[].class, 
exchange.getMessage().getBody(), body.getClass().getName());
+            Assertions.assertEquals(json, 
exchange.getMessage().getBody(String.class), body.getClass().getName());
+        }
+    }
+
+    @Test
+    void shouldWriteOtherTextAsJsonString() throws Exception {
+        // CAMEL-26300: text that is no Json object or array, as a String or 
as bytes, becomes a Json string
+        String text = "Hello \"Goofy\"";
+        for (Object body : List.of(text, 
text.getBytes(StandardCharsets.UTF_8))) {
+            Exchange exchange = new DefaultExchange(camelContext);
+            exchange.getMessage().setBody(body);
+            transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+            Assertions.assertEquals("\"Hello \\\"Goofy\\\"\"", 
exchange.getMessage().getBody(String.class),
+                    body.getClass().getName());
+            Assertions.assertEquals(text, 
Json.mapper().readTree(exchange.getMessage().getBody(byte[].class)).asString());
+        }
+    }
+
+    @Test
+    void shouldWriteJsonScalarTextAsJsonString() throws Exception {
+        // CAMEL-26300: only a Json object or array is kept as Json text, so a 
Json number, boolean, null or quoted
+        // string given as text becomes a Json string
+        Map<String, String> expected = new LinkedHashMap<>();
+        expected.put("42", "\"42\"");
+        expected.put("true", "\"true\"");
+        expected.put("null", "\"null\"");
+        expected.put("\"Hello\"", "\"\\\"Hello\\\"\"");
+        for (Map.Entry<String, String> entry : expected.entrySet()) {
+            Exchange exchange = new DefaultExchange(camelContext);
+            exchange.getMessage().setBody(entry.getKey());
+            transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+            Assertions.assertEquals(entry.getValue(), 
exchange.getMessage().getBody(String.class), entry.getKey());
+            Assertions.assertEquals(entry.getKey(),
+                    
Json.mapper().readTree(exchange.getMessage().getBody(byte[].class)).asString());
+        }
+    }
+
+    @Test
+    void shouldReadBytesWithTheExchangeCharset() throws Exception {
+        // CAMEL-26300: bytes are read as text with the charset of the 
exchange, and the Json is written in UTF-8
+        String json = "{\"name\":\"Jos\u00e9\"}";
+        Exchange exchange = new DefaultExchange(camelContext);
+        exchange.setProperty(Exchange.CHARSET_NAME, 
StandardCharsets.ISO_8859_1.name());
+        
exchange.getMessage().setBody(json.getBytes(StandardCharsets.ISO_8859_1));
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        Assertions.assertArrayEquals(json.getBytes(StandardCharsets.UTF_8), 
exchange.getMessage().getBody(byte[].class));
+
+        exchange = new DefaultExchange(camelContext);
+        exchange.setProperty(Exchange.CHARSET_NAME, 
StandardCharsets.ISO_8859_1.name());
+        
exchange.getMessage().setBody("caf\u00e9".getBytes(StandardCharsets.ISO_8859_1));
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        
Assertions.assertArrayEquals("\"caf\u00e9\"".getBytes(StandardCharsets.UTF_8),
+                exchange.getMessage().getBody(byte[].class));
+    }
+
+    @Test
+    void shouldWriteBytesInBase64WithTheByteArrayContentClass() throws 
Exception {
+        // CAMEL-26300: a payload that is not text can be given the content 
class byte[], which Jackson writes in Base64
+        Exchange exchange = new DefaultExchange(camelContext);
+        exchange.setProperty(SchemaHelper.CONTENT_CLASS, "byte[]");
+        exchange.getMessage().setBody(new byte[] { 0, 1, 2, (byte) 0xFF });
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        Assertions.assertEquals("\"AAEC/w==\"", 
exchange.getMessage().getBody(String.class));
+    }
+
     @Test
     void theBodyTypesSayTheBody() throws Exception {
-        // CAMEL-25928: Json text, a JsonNode, a POJO or a null body, as 
transformerIn says, and the Json bytes
-        // transformerOut says
+        // CAMEL-25928: Json as text, bytes or a stream, other text, a Map, a 
List, a JsonNode, a POJO or a null body,
+        // as transformerIn says, and the Json bytes transformerOut says
         BodyTypes bodyTypes = 
JsonDataTypeTransformer.class.getAnnotation(BodyTypes.class);
-        Assertions.assertEquals(List.of(Carrier.TEXT, Carrier.POJO, 
Carrier.NULL),
+        Assertions.assertEquals(
+                List.of(Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, 
Carrier.MAP, Carrier.LIST, Carrier.POJO, Carrier.NULL),
                 List.of(bodyTypes.transformerIn().value()));
         Assertions.assertEquals(List.of(Carrier.BYTES), 
List.of(bodyTypes.transformerOut().value()));
         Assertions.assertEquals(byte[].class.getCanonicalName(), 
bodyTypes.transformerOut().javaType());
         Assertions.assertEquals("json", bodyTypes.transformerOut().format());
         String json = "{ \"name\": \"Goofy\", \"age\": 25 }";
-        for (Object body : Arrays.asList(json, 
Json.mapper().readerFor(JsonNode.class).readValue(json), new Person("Goofy", 
25),
-                null)) {
+        byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
+        for (Object body : Arrays.asList(json, bytes, new 
ByteArrayInputStream(bytes), "Goofy", Map.of("name", "Goofy"),
+                List.of("Goofy"), 
Json.mapper().readerFor(JsonNode.class).readValue(json), new Person("Goofy", 
25), null)) {
             Exchange exchange = new DefaultExchange(camelContext);
             exchange.getMessage().setBody(body);
             transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
             Assertions.assertInstanceOf(byte[].class, 
exchange.getMessage().getBody(), String.valueOf(body));
         }
-        // a Map is no JsonNode, the class written without the X-Content-Class 
property
+        // with the X-Content-Class property only a body of that class
         Exchange other = new DefaultExchange(camelContext);
+        other.setProperty(SchemaHelper.CONTENT_CLASS, Person.class.getName());
         other.getMessage().setBody(Map.of("name", "Goofy"));
         Assertions.assertThrows(CamelExecutionException.class,
                 () -> transformer.transform(other.getMessage(), DataType.ANY, 
DataType.ANY));
diff --git 
a/components/camel-jackson3/src/test/java/org/apache/camel/component/jackson3/transform/JsonPojoDataTypeTransformerTest.java
 
b/components/camel-jackson3/src/test/java/org/apache/camel/component/jackson3/transform/JsonPojoDataTypeTransformerTest.java
index a800930b55ac..170ad85c72c3 100644
--- 
a/components/camel-jackson3/src/test/java/org/apache/camel/component/jackson3/transform/JsonPojoDataTypeTransformerTest.java
+++ 
b/components/camel-jackson3/src/test/java/org/apache/camel/component/jackson3/transform/JsonPojoDataTypeTransformerTest.java
@@ -27,6 +27,7 @@ import java.util.Map;
 
 import org.apache.camel.CamelExecutionException;
 import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.component.jackson3.SchemaHelper;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.spi.BodyType.Carrier;
@@ -135,6 +136,19 @@ class JsonPojoDataTypeTransformerTest {
                 () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
     }
 
+    @Test
+    void shouldFailOnNullBody() {
+        // CAMEL-26300: a null body has no Json to read, which fails as other 
bodies without Json do
+        Exchange exchange = new DefaultExchange(camelContext);
+
+        exchange.setProperty(SchemaHelper.CONTENT_CLASS, 
Person.class.getName());
+        exchange.getMessage().setBody(null);
+
+        CamelExecutionException e = 
Assertions.assertThrows(CamelExecutionException.class,
+                () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
+        Assertions.assertInstanceOf(InvalidPayloadException.class, 
e.getCause());
+    }
+
     @Test
     public void shouldLookupDataTypeTransformer() throws Exception {
         Transformer transformer = camelContext.getTransformerRegistry()
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index 5b081f718d75..a0c7ff895e8c 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -4654,6 +4654,39 @@ the record that is being routed. The other records of 
that poll (up to `maxResul
 skipped when the route was resumed. They are now routed after the resume. A 
consumer that is suspended directly
 (`consumer.suspend()`) routes all the records of its poll and was not affected.
 
+=== camel-jackson and camel-jackson3 - the bodies of the data type transformers
+
+When the `X-Content-Class` exchange property is not set, the 
`application-json` data type transformer now writes a
+`Map` body as a JSON object and a `List` (or another `Collection`) body as a 
JSON array, and reads text, bytes or a
+stream (an `InputStream`, a `Reader` or the stream cache) as text: a JSON 
object or array is kept as it is, and any
+other text becomes a JSON string, so `Hello` becomes `"Hello"`. This includes 
text that is a JSON number, boolean, null
+or quoted string: `42` becomes `"42"`, `true` becomes `"true"`, and `"Hello"` 
with its quotes becomes `"\"Hello\""`.
+These bodies failed before. With the `X-Content-Class` exchange property set, 
the transformer still writes only a body
+of that class, or JSON object or array text. A `Map` entry with a null or 
empty value is left out, as the transformer
+already did for the properties of a POJO.
+
+Bytes and a stream are read as text with the charset of the exchange (the 
`CamelCharsetName` header or exchange
+property, else UTF-8), and the JSON is written in UTF-8. A payload that is not 
text, such as Avro binary or an image,
+therefore becomes a JSON string with replacement characters. Encode such a 
payload first, for example in Base64, or
+give it a content class: a `byte[]` body with the `X-Content-Class` exchange 
property set to `byte[]` is written as a
+Base64 JSON string.
+
+The `avro-x-struct` data type transformer now reads a JSON object or array 
given as text as JSON, as
+`protobuf-x-struct` does. Before, it read the text as Avro binary, which 
failed or gave a wrong `JsonNode`.
+
+The `avro-x-java-object` and `protobuf-x-java-object` data type transformers 
of camel-jackson-avro and
+camel-jackson-protobuf now read a `JsonNode` body into the class of the 
`X-Content-Class` exchange property, as the
+camel-jackson3 ones do. Before, they failed with an 
`UnsupportedOperationException`.
+
+The `application-x-java-object`, `avro-x-java-object` and 
`protobuf-x-java-object` data type transformers now fail on a
+null body with a `CamelExecutionException`, whose cause is an 
`InvalidPayloadException`, instead of a
+`NullPointerException`, when the `X-Content-Class` exchange property is set.
+
+The `avro-binary`, `avro-x-struct`, `protobuf-binary` and `protobuf-x-struct` 
data type transformers of
+camel-jackson3-avro and camel-jackson3-protobuf now wrap a `JacksonException` 
in a `CamelExecutionException`, as their
+camel-jackson-avro and camel-jackson-protobuf counterparts and the 
camel-jackson3 JSON transformers do. The
+`JacksonException` is the cause of the `CamelExecutionException`.
+
 === camel-core - the route structure leaves out onException clauses that never 
run
 
 A route with `noErrorHandler` runs none of its `onException` clauses, and a 
global `onException` is copied into every

Reply via email to