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

struberg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/johnzon.git


The following commit(s) were added to refs/heads/master by this push:
     new c94db5ee JOHNZON-421 Defer start of object/array
c94db5ee is described below

commit c94db5ee3cd0864fb749e0445b264aa662aaad4b
Author: Mark Struberg <[email protected]>
AuthorDate: Wed Feb 11 15:00:46 2026 +0100

    JOHNZON-421 Defer start of object/array
    
    This is necessary as we don't know what Serializers/Adapters/Converters 
actually do write.
    If we start an object with { and the JsonbSerializer just writes a string 
value (json primitive)
    then we will blow up. Deferring the start fixes this issue.
---
 .../org/apache/johnzon/jsonb/JohnzonBuilder.java   |   4 +-
 .../org/apache/johnzon/jsonb/JsonbAccessMode.java  |   5 +-
 .../johnzon/jsonb/JohnzonConverterInJsonbTest.java |   5 +-
 .../org/apache/johnzon/jsonb/SerializerTest.java   |   2 +-
 .../johnzon/jsonb/SerializersRoundTripTest.java    |   3 +-
 .../SerialiseAsPrimitiveAnnotatedAtClassTest.java  | 129 ++++++++
 .../johnzon/mapper/DynamicMappingGenerator.java    |  43 +--
 .../java/org/apache/johnzon/mapper/Mapper.java     |   2 +-
 .../org/apache/johnzon/mapper/MapperConfig.java    |   4 +-
 .../apache/johnzon/mapper/MappingGenerator.java    |   7 +-
 .../johnzon/mapper/MappingGeneratorImpl.java       | 120 +++----
 .../org/apache/johnzon/mapper/ObjectConverter.java |   3 +-
 .../mapper/jsonp/DeferredStartJsonGenerator.java   | 354 +++++++++++++++++++++
 .../apache/johnzon/mapper/MapperConfigTest.java    |   5 +-
 .../mapper/ObjectConverterWithAnnotationTest.java  |   7 +-
 .../org/apache/johnzon/mapper/ObjectTypeTest.java  |  11 +-
 16 files changed, 582 insertions(+), 122 deletions(-)

diff --git 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
index 6c8daa0d..460d41c8 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
@@ -321,9 +321,9 @@ public class JohnzonBuilder implements JsonbBuilder {
                     throw new IllegalArgumentException("We only support 
serializer on Class for now");
                 }
                 builder.addObjectConverter(
-                    Class.class.cast(args[0]), (ObjectConverter.Writer) 
(instance, jsonbGenerator) ->
+                    Class.class.cast(args[0]), (ObjectConverter.Writer) 
(instance, jsonbGenerator, generator) ->
                         s.serialize(
-                                instance, jsonbGenerator.getJsonGenerator(),
+                                instance, generator,
                                 new 
JohnzonSerializationContext(jsonbGenerator)));
             });
         });
diff --git 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
index a18b3481..87f42c75 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
@@ -337,7 +337,7 @@ public class JsonbAccessMode implements AccessMode, 
Closeable, Cleanable<Class<?
                                 }
 
                                 @Override
-                                public void writeJson(final Object instance, 
final MappingGenerator jsonbGenerator) {
+                                public void writeJson(final Object instance, 
final MappingGenerator jsonbGenerator, JsonGenerator generator) {
                                     // no-op, it's for factories only
                                 }
                             };
@@ -1183,8 +1183,7 @@ public class JsonbAccessMode implements AccessMode, 
Closeable, Cleanable<Class<?
                 final JsonbSerializer jsonbSerializer = instance.getValue();
                 writer = new ObjectConverter.Writer() {
                     @Override
-                    public void writeJson(final Object instance, final 
MappingGenerator jsonbGenerator) {
-                        final JsonGenerator generator = 
jsonbGenerator.getJsonGenerator();
+                    public void writeJson(final Object instance, final 
MappingGenerator jsonbGenerator, JsonGenerator generator) {
                         jsonbSerializer.serialize(instance, generator, new 
JohnzonSerializationContext(jsonbGenerator));
                     }
 
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonConverterInJsonbTest.java
 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonConverterInJsonbTest.java
index cab88d37..24d64780 100644
--- 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonConverterInJsonbTest.java
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonConverterInJsonbTest.java
@@ -27,6 +27,7 @@ import jakarta.json.JsonObject;
 import jakarta.json.JsonValue;
 import jakarta.json.bind.Jsonb;
 import jakarta.json.bind.spi.JsonbProvider;
+import jakarta.json.stream.JsonGenerator;
 
 import org.apache.johnzon.mapper.Converter;
 import org.apache.johnzon.mapper.JohnzonConverter;
@@ -88,8 +89,8 @@ public class JohnzonConverterInJsonbTest {
         private static final String TIMESTAMP_JSON_KEY = "timestamp";
 
         @Override
-        public void writeJson(TestDTO instance, MappingGenerator 
jsonbGenerator) {
-            jsonbGenerator.getJsonGenerator().write(TIMESTAMP_JSON_KEY, 
instance.instant.atZone(ZoneId.of("UTC")).toString());
+        public void writeJson(TestDTO instance, MappingGenerator 
jsonbGenerator, JsonGenerator generator) {
+            generator.write(TIMESTAMP_JSON_KEY, 
instance.instant.atZone(ZoneId.of("UTC")).toString());
         }
 
         @Override
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java
index d640c09d..f97802d8 100644
--- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java
@@ -69,7 +69,7 @@ public class SerializerTest {
         nameHolder.name.detailName = new DetailName();
         nameHolder.name.detailName.name = "Another Test String";
         assertEquals(
-                "{\"detailName\":{\"name\":\"Another Test 
String\",\"detail\":true},\"name\":{\"name\":\"Test String\"}}",
+                "{\"name\":{\"detailName\":{\"name\":\"Another Test 
String\",\"detail\":true},\"name\":\"Test String\"}}",
                 jsonb.toJson(nameHolder));
 
     }
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializersRoundTripTest.java
 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializersRoundTripTest.java
index 88ef32e9..c6c98395 100644
--- 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializersRoundTripTest.java
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializersRoundTripTest.java
@@ -564,7 +564,8 @@ public class SerializersRoundTripTest {
         original.color = Color.GREEN;*/
 
         try (final Jsonb jsonb = JsonbBuilder.create()) {
-            final Wrapper deserialized = 
jsonb.fromJson(jsonb.toJson(original), Wrapper.class);
+            final String json = jsonb.toJson(original);
+            final Wrapper deserialized = jsonb.fromJson(json, Wrapper.class);
             assertEquals(original, deserialized);
         }
     }
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/serializer/SerialiseAsPrimitiveAnnotatedAtClassTest.java
 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/serializer/SerialiseAsPrimitiveAnnotatedAtClassTest.java
new file mode 100644
index 00000000..19ea2999
--- /dev/null
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/serializer/SerialiseAsPrimitiveAnnotatedAtClassTest.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.johnzon.jsonb.serializer;
+
+import java.lang.reflect.Type;
+
+import org.junit.Test;
+
+import jakarta.json.bind.Jsonb;
+import jakarta.json.bind.JsonbBuilder;
+import jakarta.json.bind.annotation.JsonbTypeDeserializer;
+import jakarta.json.bind.annotation.JsonbTypeSerializer;
+import jakarta.json.bind.serializer.DeserializationContext;
+import jakarta.json.bind.serializer.JsonbDeserializer;
+import jakarta.json.bind.serializer.JsonbSerializer;
+import jakarta.json.bind.serializer.SerializationContext;
+import jakarta.json.stream.JsonGenerator;
+import jakarta.json.stream.JsonParser;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * This test checks a JsonbSerialize/JsonbDeserialize roundtrip when using a 
primitive as placeholder
+ */
+public class SerialiseAsPrimitiveAnnotatedAtClassTest {
+
+
+    @JsonbTypeSerializer(ConstantJsonbSerialiser.class)
+    @JsonbTypeDeserializer(ConstantJsonbDeserializer.class)
+    public static class TestConstant {
+        public final static TestConstant VAL_1 = new TestConstant("A");
+        public final static TestConstant VAL_2 = new TestConstant("B");
+        public final static TestConstant VAL_3 = new TestConstant("C");
+
+        private final String code;
+
+        public TestConstant(String code) {
+            this.code = code;
+        }
+
+        public String getCode() {
+            return code;
+        }
+
+        public static TestConstant getByCode(String code) {
+            switch (code) {
+                case "A": return VAL_1;
+                case "B": return VAL_2;
+                case "C": return VAL_3;
+                default: return null;
+            }
+        }
+    }
+    
+    public static class ConstantUsage {
+        private int i;
+
+        private TestConstant testConstant;
+
+        public int getI() {
+            return i;
+        }
+
+        public void setI(int i) {
+            this.i = i;
+        }
+
+        public TestConstant getTestConstant() {
+            return testConstant;
+        }
+
+        public void setTestConstant(TestConstant testEnum) {
+            this.testConstant = testEnum;
+        }
+    }
+
+    public static class ConstantJsonbSerialiser implements 
JsonbSerializer<TestConstant> {
+        @Override
+        public void serialize(TestConstant val, JsonGenerator generator, 
SerializationContext ctx) {
+            if (val == null) {
+                ctx.serialize(null, generator);
+            } else {
+                ctx.serialize(val.getCode(), generator);
+            }
+        }
+    }
+
+    public static class ConstantJsonbDeserializer implements 
JsonbDeserializer<TestConstant> {
+
+    @Override
+    public TestConstant deserialize(JsonParser parser, DeserializationContext 
ctx, Type rtType) {
+        if (rtType instanceof TestConstant) {
+            final String key = parser.getString();
+            if (key != null) {
+                return TestConstant.getByCode(key);
+            }
+        }
+        
+        return null;
+    }
+}
+
+
+
+    @Test
+    public void testEnumJsonb() {
+        ConstantUsage enumVerwender = new ConstantUsage();
+        enumVerwender.setI(1);
+        enumVerwender.setTestConstant(TestConstant.VAL_2);
+        
+        Jsonb jsonb = JsonbBuilder.create();
+        final String json = jsonb.toJson(enumVerwender);
+        assertTrue(json.contains("\"testConstant\":\"B\""));
+    }
+
+}
diff --git 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/DynamicMappingGenerator.java
 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/DynamicMappingGenerator.java
index 4dce3ddd..e93c42f8 100644
--- 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/DynamicMappingGenerator.java
+++ 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/DynamicMappingGenerator.java
@@ -23,6 +23,7 @@ import jakarta.json.stream.JsonGenerator;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 
+@Deprecated
 public class DynamicMappingGenerator implements MappingGenerator {
     private final MappingGenerator delegate;
     private final Runnable writeStart;
@@ -40,33 +41,16 @@ public class DynamicMappingGenerator implements 
MappingGenerator {
         this.writeEnd = writeEnd;
         this.keyName = keyName;
     }
-
-    protected JsonGenerator getRawJsonGenerator() {
-        return delegate.getJsonGenerator();
-    }
-
-    @Override
-    public JsonGenerator getJsonGenerator() {
-        return generator == null ? generator = new 
InObjectOrPrimitiveJsonGenerator(
-                getRawJsonGenerator(), writeStart, keyName, writeEnd) : 
generator;
-    }
+    
 
     @Override
     public MappingGenerator writeObject(final String key, final Object o, 
final JsonGenerator generator) {
-        return delegate.writeObject(key, o, ensureGenerator(generator));
+        return delegate.writeObject(key, o, generator);
     }
 
     @Override
     public MappingGenerator writeObject(final Object o, final JsonGenerator 
generator) {
-        return delegate.writeObject(o, ensureGenerator(generator));
-    }
-
-    private JsonGenerator ensureGenerator(final JsonGenerator generator) {
-        if (this.generator != null && this.generator != generator && 
this.generator.delegate != generator) {
-            this.generator = null;
-            reset();
-        }
-        return getJsonGenerator(); // ensure we wrap it
+        return delegate.writeObject(o, generator);
     }
 
     protected void reset() {
@@ -593,24 +577,5 @@ public class DynamicMappingGenerator implements 
MappingGenerator {
             super(delegate, NOOP, NOOP, keyName);
             this.rawGenerator = generator;
         }
-
-        @Override
-        protected JsonGenerator getRawJsonGenerator() {
-            return rawGenerator;
-        }
-
-        @Override
-        public JsonGenerator getJsonGenerator() {
-            if (skippingGenerator == null) {
-                skippingGenerator = new 
SkipLastWriteEndGenerator(super.getJsonGenerator());
-            }
-            return skippingGenerator;
-        }
-
-        @Override
-        protected void reset() {
-            super.reset();
-            skippingGenerator = null;
-        }
     }
 }
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
index 34eb512a..267a5327 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
@@ -203,7 +203,7 @@ public class Mapper implements Closeable {
 
     private void writeObject(final Object object, final JsonGenerator 
generator, final Collection<String> ignored,
                              final JsonPointerTracker tracker) {
-        final MappingGeneratorImpl mappingGenerator = new 
MappingGeneratorImpl(config, generator, mappings);
+        final MappingGeneratorImpl mappingGenerator = new 
MappingGeneratorImpl(config, mappings);
         mappingGenerator.doWriteObject(object, generator, true, ignored, 
tracker);
     }
 
diff --git 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java
index 23b78dc9..430f03ae 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java
@@ -25,6 +25,8 @@ import org.apache.johnzon.mapper.map.LazyConverterMap;
 
 import jakarta.json.Json;
 import jakarta.json.JsonValue;
+import jakarta.json.stream.JsonGenerator;
+
 import java.lang.reflect.Type;
 import java.nio.charset.Charset;
 import java.util.Collection;
@@ -48,7 +50,7 @@ public /* DON'T MAKE IT HIDDEN */ class MapperConfig 
implements Cloneable {
 
     private static final ObjectConverter.Codec NO_CONVERTER = new 
ObjectConverter.Codec() {
         @Override
-        public void writeJson(Object instance, MappingGenerator 
jsonbGenerator) {
+        public void writeJson(Object instance, MappingGenerator 
jsonbGenerator, JsonGenerator generator) {
             // just a dummy
         }
 
diff --git 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGenerator.java 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGenerator.java
index d4ac625f..24a8378d 100644
--- 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGenerator.java
+++ 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGenerator.java
@@ -24,16 +24,11 @@ import jakarta.json.stream.JsonGenerator;
  * Handles writing Json for Objects.
  * Internally it uses a {@link JsonGenerator} to write JSON
  *
- * To write JSON-P structure elements you can use the {@link 
#getJsonGenerator()} method.
+ * To write JSON-P structure elements you can use the {@link JsonGenerator}.
  *
  */
 public interface MappingGenerator {
 
-    /**
-     * @return the {@link JsonGenerator} used internally to write the JSON 
output.
-     */
-    JsonGenerator getJsonGenerator();
-
     /**
      * Write the given Object o into the current JSON layer.
      * This will <em>not</em> open a new json layer ('{', '}')
diff --git 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java
 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java
index 4a800612..59016fc4 100644
--- 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java
+++ 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java
@@ -23,6 +23,7 @@ import static java.util.Collections.emptyMap;
 import static java.util.stream.Collectors.toList;
 
 import org.apache.johnzon.mapper.internal.JsonPointerTracker;
+import org.apache.johnzon.mapper.jsonp.DeferredStartJsonGenerator;
 import org.apache.johnzon.mapper.util.ArrayUtil;
 
 import jakarta.json.JsonValue;
@@ -44,21 +45,14 @@ import java.util.stream.StreamSupport;
 
 public class MappingGeneratorImpl implements MappingGenerator {
     private final MapperConfig config;
-    private final JsonGenerator generator;
     private final Mappings mappings;
     private Map<Object, String> jsonPointers;
 
-    MappingGeneratorImpl(MapperConfig config, JsonGenerator jsonGenerator, 
final Mappings mappings) {
+    MappingGeneratorImpl(MapperConfig config, final Mappings mappings) {
         this.config = config;
-        this.generator = jsonGenerator;
         this.mappings = mappings;
     }
 
-    @Override
-    public JsonGenerator getJsonGenerator() {
-        return generator;
-    }
-
     @Override
     public MappingGenerator writeObject(final String key, final Object object, 
final JsonGenerator generator) {
         if (object == null) {
@@ -86,8 +80,9 @@ public class MappingGeneratorImpl implements MappingGenerator 
{
                 } else {
                     final ObjectConverter.Writer objectConverter = 
config.findObjectConverterWriter(objectClass);
                     if (objectConverter != null) {
-                        writeWithObjectConverter(new 
DynamicMappingGenerator(this,
-                                generator::writeStartObject, 
generator::writeEnd, null), objectConverter, object);
+                        DeferredStartJsonGenerator deferredStartJsonGenerator 
= new DeferredStartJsonGenerator(generator, key);
+                        objectConverter.writeJson(object, this, 
deferredStartJsonGenerator);
+                        deferredStartJsonGenerator.writeEnd();
                     } else {
                         writeValue(objectClass, false, false, false, false, 
false, null, key, object,
                                 null, emptyList(), isDedup() ? 
JsonPointerTracker.ROOT : null, generator);
@@ -124,7 +119,7 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
                 if (writeBody) {
                     generator.writeStartObject();
                 }
-                writeMapBody((Map<?, ?>) object, null);
+                writeMapBody((Map<?, ?>) object, null, generator);
                 if (writeBody) {
                     generator.writeEnd();
                 }
@@ -145,12 +140,12 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
 
             if (objectClass.isArray()) {
                 final Adapter adapter = config.findAdapter(objectClass);
-                writeArray(objectClass, adapter, null, object, 
ignoredProperties, jsonPointer);
+                writeArray(objectClass, adapter, null, object, 
ignoredProperties, jsonPointer, generator);
                 return;
             }
 
             if (object instanceof Iterable) {
-                doWriteIterable((Iterable) object, ignoredProperties, 
jsonPointer);
+                doWriteIterable((Iterable) object, ignoredProperties, 
jsonPointer, generator);
                 return;
             }
 
@@ -172,10 +167,11 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
             ObjectConverter.Writer objectConverter = 
config.findObjectConverterWriter(objectClass);
             if (writeBody && objectConverter != null) {
                 if (!writeBody) {
-                    objectConverter.writeJson(object, this);
+                    objectConverter.writeJson(object, this, generator);
                 } else {
-                    writeWithObjectConverter(new DynamicMappingGenerator(this,
-                            generator::writeStartObject, generator::writeEnd, 
null), objectConverter, object);
+                    DeferredStartJsonGenerator deferredGenerator = new 
DeferredStartJsonGenerator(generator, null);
+                    objectConverter.writeJson(object, this, deferredGenerator);
+                    deferredGenerator.writeEnd();
                 }
             } else {
                 if (classMapping == null) { // will be created anyway now so 
force it and if it has an adapter respect it
@@ -189,7 +185,7 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
                 }
 
                 if (writeBody) {
-                    generator.writeStartObject();
+                    generator = new DeferredStartJsonGenerator(generator, 
null);
                 }
 
                 final boolean writeEnd = doWriteObjectBody(object, 
ignoredProperties, jsonPointer, generator);
@@ -202,8 +198,10 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
         }
     }
 
-    private JsonGenerator writeMapBody(final Map<?, ?> object, final Adapter 
itemConverter) throws InvocationTargetException, IllegalAccessException {
-        for (final Map.Entry<?, ?> entry : ((Map<?, ?>) object).entrySet()) {
+    private JsonGenerator writeMapBody(final Map<?, ?> object, final Adapter 
itemConverter,
+                                       final JsonGenerator generator)
+            throws InvocationTargetException, IllegalAccessException {
+        for (final Map.Entry<?, ?> entry : object.entrySet()) {
             final Object value = entry.getValue();
             final Object key = entry.getKey();
 
@@ -363,7 +361,9 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
         }
 
         if (classMapping.writer != null) {
-            writeWithObjectConverter(new 
DynamicMappingGenerator.SkipEnclosingWriteEnd(this, null, generator), 
classMapping.writer, object);
+            DeferredStartJsonGenerator deferredStartJsonGenerator = new 
DeferredStartJsonGenerator(generator, null);
+            classMapping.writer.writeJson(object, this, 
deferredStartJsonGenerator);
+            deferredStartJsonGenerator.writeEnd();
             return false;
         }
         if (classMapping.adapter != null) {
@@ -429,7 +429,7 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
         if (classMapping.anyGetter != null) {
             final Map<String, Object> any = 
Map.class.cast(classMapping.anyGetter.reader.read(object));
             if (any != null) {
-                writeMapBody(any, null);
+                writeMapBody(any, null, generator);
             }
         }
 
@@ -452,23 +452,23 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
             return;
         }
         if ((!dynamic && array) || (dynamic && type.isArray())) {
-            writeArray(type, itemConverter, key, value, ignoredProperties, 
jsonPointer);
+            writeArray(type, itemConverter, key, value, ignoredProperties, 
jsonPointer, generator);
         } else if ((!dynamic && collection) || (dynamic && 
Iterable.class.isAssignableFrom(type))) {
             writeIterator(itemConverter, key, objectConverter, 
ignoredProperties, jsonPointer, generator,
                     Iterable.class.cast(value).iterator(), value);
         } else if ((!dynamic && map) || (dynamic && 
Map.class.isAssignableFrom(type))) {
-            generator.writeStartObject(key);
+            DeferredStartJsonGenerator deferredStartJsonGenerator = new 
DeferredStartJsonGenerator(generator, key);
             if (objectConverter != null) {
-                writeWithObjectConverter(new DynamicMappingGenerator(this,
-                        () -> this.generator.writeStartObject(key), 
this.generator::writeEnd, key), objectConverter, value);
+                objectConverter.writeJson(value, this, 
deferredStartJsonGenerator);
             } else {
-                writeMapBody((Map<?, ?>) value, itemConverter);
+                writeMapBody((Map<?, ?>) value, itemConverter, 
deferredStartJsonGenerator);
             }
-            generator.writeEnd();
+            deferredStartJsonGenerator.writeEnd();
         } else if ((!dynamic && primitive) || (dynamic && 
Mappings.isPrimitive(type))) {
             if (objectConverter != null) {
-                writeWithObjectConverter(new DynamicMappingGenerator(this,
-                        () -> this.generator.writeStartObject(key), 
this.generator::writeEnd, key), objectConverter, value);
+                DeferredStartJsonGenerator deferredStartJsonGenerator = new 
DeferredStartJsonGenerator(generator, key);
+                objectConverter.writeJson(value, this, 
deferredStartJsonGenerator);
+                deferredStartJsonGenerator.writeEnd();
             } else {
                 writePrimitives(key, type, value, generator);
             }
@@ -478,8 +478,9 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
         } else if (Iterator.class.isAssignableFrom(type)) {
             if (objectConverter != null) {
                 generator.writeStartObject(key);
+                //X TODO 2 writeStartObject? sounds fishy...
                 writeWithObjectConverter(new DynamicMappingGenerator(this,
-                        () -> this.generator.writeStartObject(key), 
this.generator::writeEnd, key), objectConverter, value);
+                        () -> generator.writeStartObject(key), 
generator::writeEnd, key), objectConverter, value, generator);
                 generator.writeEnd();
             } else {
                 writeIterator(itemConverter, key, objectConverter, 
ignoredProperties, jsonPointer, generator,
@@ -487,8 +488,9 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
             }
         } else {
             if (objectConverter != null) {
-                writeWithObjectConverter(new DynamicMappingGenerator(this,
-                        () -> this.generator.writeStartObject(key), 
this.generator::writeEnd, key), objectConverter, value);
+                DeferredStartJsonGenerator deferredStartJsonGenerator = new 
DeferredStartJsonGenerator(generator, key);
+                objectConverter.writeJson(value, this, 
deferredStartJsonGenerator);
+                deferredStartJsonGenerator.writeEnd();
                 return;
             }
 
@@ -507,26 +509,27 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
                 }
 
                 if (objectConverterToUse != null) {
-                    writeWithObjectConverter(new DynamicMappingGenerator(this,
-                            () -> this.generator.writeStartObject(key), 
this.generator::writeEnd, key), objectConverterToUse, value);
+                    DeferredStartJsonGenerator deferredStartJsonGenerator = 
new DeferredStartJsonGenerator(generator, key);
+                    objectConverterToUse.writeJson(value, this, 
deferredStartJsonGenerator);
+                    deferredStartJsonGenerator.writeEnd();
                     return;
                 }
             }
             if (writePrimitives(key, type, value, generator)) {
                 return;
             }
-            generator.writeStartObject(key);
-            if (doWriteObjectBody(value, ignoredProperties, jsonPointer, 
generator)) {
-                generator.writeEnd();
+            DeferredStartJsonGenerator deferredStartGenerator = new 
DeferredStartJsonGenerator(generator, key);
+            if (doWriteObjectBody(value, ignoredProperties, jsonPointer, 
deferredStartGenerator)) {
+                deferredStartGenerator.writeEnd();
             }
         }
     }
 
-    private void writeWithObjectConverter(final DynamicMappingGenerator 
generator,
+    @Deprecated
+    private void writeWithObjectConverter(final DynamicMappingGenerator 
dynamicMappingGenerator,
                                           final ObjectConverter.Writer 
objectConverter,
-                                          final Object value) {
-        final DynamicMappingGenerator dynamicMappingGenerator = generator;
-        objectConverter.writeJson(value, dynamicMappingGenerator);
+                                          final Object value, JsonGenerator 
generator) {
+        objectConverter.writeJson(value, dynamicMappingGenerator, generator);
         dynamicMappingGenerator.flushIfNeeded();
     }
 
@@ -542,8 +545,9 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
                     List.class.cast(originalValue) :
                     
StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 
Spliterator.IMMUTABLE), false)
                         .collect(toList());
-            objectConverter.writeJson(list, new DynamicMappingGenerator(
-                    this, generator::writeStartArray, generator::writeEnd, 
key));
+            DeferredStartJsonGenerator deferredStartJsonGenerator = new 
DeferredStartJsonGenerator(generator, key, true);
+            objectConverter.writeJson(list, this, deferredStartJsonGenerator);
+            deferredStartJsonGenerator.writeEnd();
             return;
         }
 
@@ -562,11 +566,12 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
                 }
 
                 if (objectConverterToUse != null) {
-                    writeWithObjectConverter(new DynamicMappingGenerator(this,
-                            generator::writeStartObject, generator::writeEnd, 
null), objectConverterToUse, o);
+                    DeferredStartJsonGenerator deferredStartJsonGenerator = 
new DeferredStartJsonGenerator(generator, null);
+                    objectConverterToUse.writeJson(o, this, 
deferredStartJsonGenerator);
+                    deferredStartJsonGenerator.writeEnd();
                 } else {
                     writeItem(itemConverter != null ? itemConverter.from(o) : 
o, ignoredProperties,
-                            isDedup() ? new JsonPointerTracker(jsonPointer, i) 
: null);
+                            isDedup() ? new JsonPointerTracker(jsonPointer, i) 
: null, generator);
                 }
             }
             i++;
@@ -576,9 +581,12 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
 
     /**
      * Write a JSON Array with a given Array Value, like byte[], int[], 
Person[] etc.
-     * @param key either the attribute key or {@code null} if the array should 
be rendered without key
+     *
+     * @param key       either the attribute key or {@code null} if the array 
should be rendered without key
+     * @param generator
      */
-    private void writeArray(Class<?> type, Adapter itemConverter, String key, 
Object arrayValue, Collection<String> ignoredProperties, JsonPointerTracker 
jsonPointer) {
+    private void writeArray(Class<?> type, Adapter itemConverter, String key, 
Object arrayValue, Collection<String> ignoredProperties, JsonPointerTracker 
jsonPointer,
+                            final JsonGenerator generator) {
         final int length = ArrayUtil.getArrayLength(arrayValue);
         if (length == 0 && config.isSkipEmptyArray()) {
             return;
@@ -671,7 +679,7 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
             for (int i = 0; i < length; i++) {
                 final Object o = oArrayValue[i];
                 writeItem(itemConverter != null ? itemConverter.from(o) : o, 
ignoredProperties,
-                        isDedup() ? new JsonPointerTracker(jsonPointer, i) : 
null);
+                        isDedup() ? new JsonPointerTracker(jsonPointer, i) : 
null, generator);
             }
         } else {
             // must be object arrays
@@ -686,7 +694,7 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
                     generator.write((JsonValue) o);
                 } else {
                     writeItem(itemConverter != null ? itemConverter.from(o) : 
o, ignoredProperties,
-                            isDedup() ? new JsonPointerTracker(jsonPointer, i) 
: null);
+                            isDedup() ? new JsonPointerTracker(jsonPointer, i) 
: null, generator);
                 }
             }
         }
@@ -694,16 +702,17 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
     }
 
 
-    private void writeItem(final Object o, final Collection<String> 
ignoredProperties, JsonPointerTracker jsonPointer) {
+    private void writeItem(final Object o, final Collection<String> 
ignoredProperties, JsonPointerTracker jsonPointer,
+                           final JsonGenerator generator) {
         if (o == null) {
             generator.writeNull();
         } else if (!writePrimitives(o, generator)) {
             if (Collection.class.isInstance(o)) {
-                doWriteIterable(Collection.class.cast(o), ignoredProperties, 
jsonPointer);
+                doWriteIterable(Collection.class.cast(o), ignoredProperties, 
jsonPointer, generator);
             } else if (o.getClass().isArray()) {
                 final int length = ArrayUtil.getArrayLength(o);
                 if (length > 0 || !config.isSkipEmptyArray()) {
-                    writeArray(o.getClass(), null, null, o, ignoredProperties, 
jsonPointer);
+                    writeArray(o.getClass(), null, null, o, ignoredProperties, 
jsonPointer, generator);
                 }
             } else {
                 String valJsonPointer = jsonPointers == null ? null : 
jsonPointers.get(o);
@@ -717,7 +726,8 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
         }
     }
 
-    private <T> void doWriteIterable(final Iterable<T> object, final 
Collection<String> ignoredProperties, JsonPointerTracker jsonPointer) {
+    private <T> void doWriteIterable(final Iterable<T> object, final 
Collection<String> ignoredProperties, JsonPointerTracker jsonPointer,
+                                     final JsonGenerator generator) {
         if (object == null) {
             generator.writeStartArray().writeEnd();
         } else {
@@ -730,7 +740,7 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
                     if (t == null) {
                         generator.writeNull();
                     } else {
-                        writeItem(t, ignoredProperties, isDedup() ? new 
JsonPointerTracker(jsonPointer, i) : null);
+                        writeItem(t, ignoredProperties, isDedup() ? new 
JsonPointerTracker(jsonPointer, i) : null, generator);
                     }
                 }
                 i++;
diff --git 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ObjectConverter.java 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ObjectConverter.java
index 57098715..ceee7a6a 100644
--- 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ObjectConverter.java
+++ 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ObjectConverter.java
@@ -19,6 +19,7 @@
 package org.apache.johnzon.mapper;
 
 import jakarta.json.JsonValue;
+import jakarta.json.stream.JsonGenerator;
 
 import java.lang.reflect.Type;
 
@@ -36,7 +37,7 @@ public final class ObjectConverter {
     }
 
     public interface Writer<T> extends MapperConverter {
-        void writeJson(T instance, MappingGenerator jsonbGenerator);
+        void writeJson(T instance, MappingGenerator jsonbGenerator, 
JsonGenerator generator);
 
         // returns true if it is for containers - if any - and not each 
container item (ex: list)
         default boolean isGlobal() {
diff --git 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/jsonp/DeferredStartJsonGenerator.java
 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/jsonp/DeferredStartJsonGenerator.java
new file mode 100644
index 00000000..b6909274
--- /dev/null
+++ 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/jsonp/DeferredStartJsonGenerator.java
@@ -0,0 +1,354 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.johnzon.mapper.jsonp;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import jakarta.json.JsonValue;
+import jakarta.json.stream.JsonGenerator;
+
+
+/**
+ * This JsonGenerator will not automatically write a startObject '{' 
character, but only if needed.
+ *
+ * The {@link #writeEnd()} method will only write a closing '}' if a start has 
been written before.
+ * 
+ * This class must only be used in cases where you would call {@code 
jsonGenerator.startObject(key)} !
+ */
+public class DeferredStartJsonGenerator implements JsonGenerator {
+
+    private final JsonGenerator delegate;
+    private final String key;
+    private final boolean array;
+
+    private boolean started = false;
+    private boolean empty = true;
+
+    // this is needed to make sure we don't close more layers than we did open.
+    private int depth = 0;
+
+    /**
+     * Deferred start for Objects
+     *
+     * @see #DeferredStartJsonGenerator(JsonGenerator, String, boolean)
+     */
+    public DeferredStartJsonGenerator(JsonGenerator delegate, String key) {
+        this(delegate, key, false);
+    }
+
+    /**
+     * JsonGenerator which only writes a start character if an embedded json 
structure is later written.
+     *
+     * @param delegate JsonGenerator which really writes
+     * @param key for the startObject, or {@code null} if no key should be used
+     * @param array if {@code true} we will use a start with a '[', otherwise 
with an object start '{'
+     */
+    public DeferredStartJsonGenerator(JsonGenerator delegate, String key, 
boolean array) {
+        this.delegate = delegate;
+        this.key = key;
+        this.array = array;
+    }
+
+    private void ensureStart() {
+        if (!started) {
+            if (array) {
+                if (key != null) {
+                    delegate.writeStartArray(key);
+                } else {
+                    delegate.writeStartArray();
+                }
+            } else {
+                if (key != null) {
+                    delegate.writeStartObject(key);
+                } else {
+                    delegate.writeStartObject();
+                }
+            }
+            started = true;
+            depth++;
+        }
+    }
+
+    @Override
+    public void close() {
+        writeEnd();
+        delegate.close();
+    }
+
+    @Override
+    public void flush() {
+        delegate.flush();
+    }
+
+    @Override
+    public JsonGenerator write(String name, BigDecimal value) {
+        ensureStart();
+        empty = false;
+        delegate.write(name, value);
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(String name, BigInteger value) {
+        ensureStart();
+        delegate.write(name, value);
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(String name, boolean value) {
+        ensureStart();
+        delegate.write(name, value);
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(String name, double value) {
+        ensureStart();
+        delegate.write(name, value);
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(String name, int value) {
+        ensureStart();
+        delegate.write(name, value);
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(String name, JsonValue value) {
+        ensureStart();
+        delegate.write(name, value);
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(String name, long value) {
+        ensureStart();
+        delegate.write(name, value);
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(String name, String value) {
+        ensureStart();
+        delegate.write(name, value);
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(BigDecimal value) {
+        if (!started && key != null) {
+            // means we write a value instead of an object
+            delegate.write(key, value);
+        } else {
+            delegate.write(value);
+        }
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(BigInteger value) {
+        if (!started && key != null) {
+            // means we write a value instead of an object
+            delegate.write(key, value);
+        } else {
+            delegate.write(value);
+        }
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(boolean value) {
+        if (!started && key != null) {
+            // means we write a value instead of an object
+            delegate.write(key, value);
+        } else {
+            delegate.write(value);
+        }
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(double value) {
+        if (!started && key != null) {
+            // means we write a value instead of an object
+            delegate.write(key, value);
+        } else {
+            delegate.write(value);
+        }
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(int value) {
+        if (!started && key != null) {
+            // means we write a value instead of an object
+            delegate.write(key, value);
+        } else {
+            delegate.write(value);
+        }
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(JsonValue value) {
+        if (!started && key != null) {
+            // means we write a value instead of an object
+            delegate.write(key, value);
+        } else {
+            delegate.write(value);
+        }
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(long value) {
+        if (!started && key != null) {
+            // means we write a value instead of an object
+            delegate.write(key, value);
+        } else {
+            delegate.write(value);
+        }
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator write(String value) {
+        if (!started && key != null) {
+            // means we write a value instead of an object
+            delegate.write(key, value);
+        } else {
+            delegate.write(value);
+        }
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator writeEnd() {
+        if (empty) {
+            if (key != null) {
+                delegate.writeStartObject(key);
+            } else {
+                delegate.writeStartObject();
+            }
+            started = true;
+            depth++;
+        }
+        if (started && depth > 0) {
+            delegate.writeEnd();
+            depth--;
+        }
+
+
+        return this;
+    }
+
+    @Override
+    public JsonGenerator writeKey(String name) {
+        delegate.writeKey(name);
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator writeNull() {
+        if (!started && key != null) {
+            // means we write a value instead of an object
+            delegate.writeNull(key);
+        } else {
+            delegate.writeNull();
+        }
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator writeNull(String name) {
+        ensureStart();
+        delegate.writeNull(name);
+        empty = false;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator writeStartArray() {
+        // safeguard if Converters, Serializers ets do a manual startArray()
+        if (key != null && !started) {
+            delegate.writeStartArray(key);
+        } else {
+            delegate.writeStartArray();
+        }
+        started = true;
+        empty = false;
+        depth++;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator writeStartArray(String name) {
+        ensureStart();
+        delegate.writeStartArray(name);
+        started = true;
+        empty = false;
+        depth++;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator writeStartObject() {
+        // safeguard if Converters, Serializers ets do a manual startObject()
+        if (key != null && !started) {
+            delegate.writeStartObject(key);
+        } else {
+            delegate.writeStartObject();
+        }
+
+        started = true;
+        empty = false;
+        depth++;
+        return this;
+    }
+
+    @Override
+    public JsonGenerator writeStartObject(String name) {
+        ensureStart();
+        started = true;
+        delegate.writeStartObject(name);
+        empty = false;
+        depth++;
+        return this;
+    }
+}
diff --git 
a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java 
b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java
index c9429536..5f42d8e2 100644
--- 
a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java
+++ 
b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java
@@ -27,6 +27,7 @@ import org.junit.Assert;
 import org.junit.Test;
 
 import jakarta.json.JsonValue;
+import jakarta.json.stream.JsonGenerator;
 
 import java.lang.reflect.Type;
 import java.nio.charset.StandardCharsets;
@@ -189,7 +190,7 @@ public class MapperConfigTest {
 
     private static class TheConverter<T> implements ObjectConverter.Codec<T>{
         @Override
-        public void writeJson(T instance, MappingGenerator jsonbGenerator) {
+        public void writeJson(T instance, MappingGenerator jsonbGenerator, 
JsonGenerator generator) {
             // dummy
         }
 
@@ -202,7 +203,7 @@ public class MapperConfigTest {
 
     private static abstract class TheAbstractConverter<T extends TheInterface> 
implements ObjectConverter.Codec<T> {
         @Override
-        public void writeJson(T instance, MappingGenerator jsonbGenerator) {
+        public void writeJson(T instance, MappingGenerator jsonbGenerator, 
JsonGenerator generator) {
             // dummy
         }
 
diff --git 
a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java
 
b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java
index 82ae4614..cca78423 100644
--- 
a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java
+++ 
b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java
@@ -24,6 +24,7 @@ import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
 import jakarta.json.JsonValue;
+import jakarta.json.stream.JsonGenerator;
 
 import java.beans.ConstructorProperties;
 import java.lang.reflect.Type;
@@ -388,11 +389,11 @@ public class ObjectConverterWithAnnotationTest {
 
 
         @Override
-        public void writeJson(Bike instance, MappingGenerator jsonbGenerator) {
-            jsonbGenerator.getJsonGenerator().write(MANUFACTURER_ID, 
MANUFACTURERS.indexOf(instance.getManufacturer()));
+        public void writeJson(Bike instance, MappingGenerator jsonbGenerator, 
JsonGenerator generator) {
+            generator.write(MANUFACTURER_ID, 
MANUFACTURERS.indexOf(instance.getManufacturer()));
 
             // i know you should never use this in production but its good for 
our sample ;)
-            jsonbGenerator.getJsonGenerator().write(TYPE_INDEX, 
instance.getType().ordinal());
+            generator.write(TYPE_INDEX, instance.getType().ordinal());
         }
 
         @Override
diff --git 
a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java 
b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java
index 36c76161..38300297 100644
--- a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java
+++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java
@@ -25,6 +25,7 @@ import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
 import jakarta.json.JsonValue;
+import jakarta.json.stream.JsonGenerator;
 
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
@@ -200,9 +201,9 @@ public class ObjectTypeTest {
 
     public static class TestWithTypeConverter implements 
ObjectConverter.Codec<Dog> {
         @Override
-        public void writeJson(Dog instance, MappingGenerator mappingGenerator) 
{
-            mappingGenerator.getJsonGenerator().write("//javaType", 
instance.getClass().getName());
-            mappingGenerator.writeObject(instance, 
mappingGenerator.getJsonGenerator());
+        public void writeJson(Dog instance, MappingGenerator mappingGenerator, 
JsonGenerator generator) {
+            generator.write("//javaType", instance.getClass().getName());
+            mappingGenerator.writeObject(instance, generator);
         }
 
         @Override
@@ -420,8 +421,8 @@ public class ObjectTypeTest {
         }
 
         @Override
-        public void writeJson(Poodle instance, MappingGenerator 
jsonbGenerator) {
-            jsonbGenerator.getJsonGenerator().write("poodleName", 
instance.getName());
+        public void writeJson(Poodle instance, MappingGenerator 
jsonbGenerator, JsonGenerator generator) {
+            generator.write("poodleName", instance.getName());
         }
 
         @Override

Reply via email to