Skip to content

Commit c77759f

Browse files
committed
JOHNZON-421 JsonbSerializer crashes when using primitives
If an object is serialised into a primitive, then we did crash with an Exception JsonGenerationException: write(param) is only valid in arrays.
1 parent b54d5e4 commit c77759f

File tree

2 files changed

+134
-4
lines changed

2 files changed

+134
-4
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.johnzon.jsonb.serializer;
18+
19+
import java.lang.reflect.Type;
20+
21+
import org.junit.Test;
22+
23+
import jakarta.json.bind.Jsonb;
24+
import jakarta.json.bind.JsonbBuilder;
25+
import jakarta.json.bind.annotation.JsonbTypeDeserializer;
26+
import jakarta.json.bind.annotation.JsonbTypeSerializer;
27+
import jakarta.json.bind.serializer.DeserializationContext;
28+
import jakarta.json.bind.serializer.JsonbDeserializer;
29+
import jakarta.json.bind.serializer.JsonbSerializer;
30+
import jakarta.json.bind.serializer.SerializationContext;
31+
import jakarta.json.stream.JsonGenerator;
32+
import jakarta.json.stream.JsonParser;
33+
import static org.junit.Assert.assertTrue;
34+
35+
/**
36+
* This test checks a JsonbSerialize/JsonbDeserialize roundtrip when using a primitive as placeholder
37+
*/
38+
public class SerialiseAsPrimitiveTest {
39+
40+
41+
public static class TestConstant {
42+
public final static TestConstant VAL_1 = new TestConstant("A");
43+
public final static TestConstant VAL_2 = new TestConstant("B");
44+
public final static TestConstant VAL_3 = new TestConstant("C");
45+
46+
private final String code;
47+
48+
public TestConstant(String code) {
49+
this.code = code;
50+
}
51+
52+
public String getCode() {
53+
return code;
54+
}
55+
56+
public static TestConstant getByCode(String code) {
57+
switch (code) {
58+
case "A": return VAL_1;
59+
case "B": return VAL_2;
60+
case "C": return VAL_3;
61+
default: return null;
62+
}
63+
}
64+
}
65+
66+
public static class ConstantUsage {
67+
private int i;
68+
69+
@JsonbTypeSerializer(ConstantJsonbSerialiser.class)
70+
@JsonbTypeDeserializer(ConstantJsonbDeserializer.class)
71+
private TestConstant testConstant;
72+
73+
public int getI() {
74+
return i;
75+
}
76+
77+
public void setI(int i) {
78+
this.i = i;
79+
}
80+
81+
public TestConstant getTestConstant() {
82+
return testConstant;
83+
}
84+
85+
public void setTestConstant(TestConstant testEnum) {
86+
this.testConstant = testEnum;
87+
}
88+
}
89+
90+
public static class ConstantJsonbSerialiser implements JsonbSerializer<TestConstant> {
91+
@Override
92+
public void serialize(TestConstant val, JsonGenerator generator, SerializationContext ctx) {
93+
if (val == null) {
94+
ctx.serialize(null, generator);
95+
} else {
96+
ctx.serialize(val.getCode(), generator);
97+
}
98+
}
99+
}
100+
101+
public static class ConstantJsonbDeserializer implements JsonbDeserializer<TestConstant> {
102+
103+
@Override
104+
public TestConstant deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) {
105+
if (rtType instanceof TestConstant) {
106+
final String key = parser.getString();
107+
if (key != null) {
108+
return TestConstant.getByCode(key);
109+
}
110+
}
111+
112+
return null;
113+
}
114+
}
115+
116+
117+
118+
@Test
119+
public void testEnumJsonb() {
120+
ConstantUsage enumVerwender = new ConstantUsage();
121+
enumVerwender.setI(1);
122+
enumVerwender.setTestConstant(TestConstant.VAL_2);
123+
124+
Jsonb jsonb = JsonbBuilder.create();
125+
final String json = jsonb.toJson(enumVerwender);
126+
assertTrue(json.contains("\"testConstant\":\"B\""));
127+
}
128+
129+
}

johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public void doWriteObject(Object object, JsonGenerator generator, boolean writeB
131131
return;
132132
}
133133

134-
if (writePrimitives(object)) {
134+
if (writePrimitives(object, generator)) {
135135
return;
136136
}
137137

@@ -231,7 +231,8 @@ private JsonGenerator writeMapBody(final Map<?, ?> object, final Adapter itemCon
231231
/**
232232
* @return {@code true} if it was a primitive, {@code false} if the value did not get handled
233233
*/
234-
private boolean writePrimitives(final Object value) {
234+
private boolean writePrimitives(final Object value,
235+
final JsonGenerator generator) {
235236
boolean handled = false;
236237
if (value == null) {
237238
return true; // fake a write
@@ -550,7 +551,7 @@ private void writeIterator(final Adapter itemConverter, final String key,
550551
String valJsonPointer = jsonPointers == null ? null : jsonPointers.get(o);
551552
if (valJsonPointer != null) {
552553
// write JsonPointer instead of the original object
553-
writePrimitives(valJsonPointer);
554+
writePrimitives(valJsonPointer, generator);
554555
} else {
555556
ObjectConverter.Writer objectConverterToUse = objectConverter;
556557
if (o != null && objectConverterToUse == null) {
@@ -693,7 +694,7 @@ private void writeArray(Class<?> type, Adapter itemConverter, String key, Object
693694
private void writeItem(final Object o, final Collection<String> ignoredProperties, JsonPointerTracker jsonPointer) {
694695
if (o == null) {
695696
generator.writeNull();
696-
} else if (!writePrimitives(o)) {
697+
} else if (!writePrimitives(o, generator)) {
697698
if (Collection.class.isInstance(o)) {
698699
doWriteIterable(Collection.class.cast(o), ignoredProperties, jsonPointer);
699700
} else if (o.getClass().isArray()) {

0 commit comments

Comments
 (0)