Skip to content

Commit c92fce8

Browse files
committed
Fix FasterXML#571: Address PR comments
1 parent 0510423 commit c92fce8

File tree

3 files changed

+51
-39
lines changed

3 files changed

+51
-39
lines changed

ion/src/main/java/com/fasterxml/jackson/dataformat/ion/IonParser.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,13 @@ private IonValue getIonValue() throws IOException {
576576
IonValue v = l.get(0);
577577
v.removeFromContainer();
578578

579-
if (v.isNullValue() && !Feature.READ_NULL_AS_IONVALUE.enabledIn(_formatFeatures)) {
580-
if (_valueToken == JsonToken.VALUE_NULL && !IonType.isContainer(v.getType())) {
579+
if (!Feature.READ_NULL_AS_IONVALUE.enabledIn(_formatFeatures)) {
580+
// 2025-04-11, seadbrane: The default is to read 'null' as an Ion Null object.
581+
// However, there is no way to determine from the serialized ion data if a 'null'
582+
// was an IonNullValue or a 'null' container type such as IonNullStruct or IonNullList.
583+
// So if READ_NULL_AS_IONVALUE is disabled, then return 'null' if the _valueToken
584+
// is 'null' and the Ion value read is not container type already.
585+
if (v.isNullValue() && _valueToken == JsonToken.VALUE_NULL && !IonType.isContainer(v.getType())) {
581586
return null;
582587
}
583588
}

ion/src/main/java/com/fasterxml/jackson/dataformat/ion/ionvalue/IonValueDeserializer.java

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,36 +18,25 @@
1818

1919
import com.fasterxml.jackson.core.JsonParser;
2020
import com.fasterxml.jackson.core.JsonToken;
21-
import com.fasterxml.jackson.databind.BeanProperty;
22-
import com.fasterxml.jackson.databind.DeserializationContext;
23-
import com.fasterxml.jackson.databind.JavaType;
24-
import com.fasterxml.jackson.databind.JsonMappingException;
21+
import com.fasterxml.jackson.databind.*;
2522
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
26-
import com.fasterxml.jackson.databind.JsonDeserializer;
2723
import com.fasterxml.jackson.databind.util.AccessPattern;
2824
import com.fasterxml.jackson.dataformat.ion.IonParser;
29-
import com.amazon.ion.IonContainer;
30-
import com.amazon.ion.IonList;
31-
import com.amazon.ion.IonSexp;
32-
import com.amazon.ion.IonStruct;
33-
import com.amazon.ion.IonSystem;
34-
import com.amazon.ion.IonType;
35-
import com.amazon.ion.IonValue;
36-
import com.amazon.ion.Timestamp;
25+
import com.amazon.ion.*;
3726

3827
/**
3928
* Deserializer that knows how to deserialize an IonValue.
4029
*/
4130
class IonValueDeserializer extends JsonDeserializer<IonValue> implements ContextualDeserializer {
4231

43-
private final JavaType targetType;
32+
private final JavaType _targetType;
4433

4534
public IonValueDeserializer() {
46-
this.targetType = null;
35+
this._targetType = null;
4736
}
4837

4938
public IonValueDeserializer(JavaType targetType) {
50-
this.targetType = targetType;
39+
this._targetType = targetType;
5140
}
5241

5342
@Override
@@ -111,8 +100,8 @@ public IonValue getNullValue(DeserializationContext ctxt) throws JsonMappingExce
111100
}
112101

113102
private IonType getIonContainerType() {
114-
if (targetType != null) {
115-
Class<?> clazz = targetType.getRawClass();
103+
if (_targetType != null) {
104+
Class<?> clazz = _targetType.getRawClass();
116105
if (IonStruct.class.isAssignableFrom(clazz)) return IonType.STRUCT;
117106
if (IonList.class.isAssignableFrom(clazz)) return IonType.LIST;
118107
if (IonSexp.class.isAssignableFrom(clazz)) return IonType.SEXP;

ion/src/test/java/com/fasterxml/jackson/dataformat/ion/ionvalue/IonValueDeserializerTest.java

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package com.fasterxml.jackson.dataformat.ion.ionvalue;
22

3+
import com.amazon.ion.IonList;
34
import com.amazon.ion.IonSystem;
45
import com.amazon.ion.IonValue;
56
import com.amazon.ion.IonStruct;
67
import com.amazon.ion.system.IonSystemBuilder;
78
import com.fasterxml.jackson.annotation.JsonAnyGetter;
89
import com.fasterxml.jackson.annotation.JsonAnySetter;
10+
import com.fasterxml.jackson.annotation.JsonInclude;
911
import com.fasterxml.jackson.annotation.JsonProperty;
12+
import com.fasterxml.jackson.databind.ObjectWriter;
1013
import com.fasterxml.jackson.databind.util.AccessPattern;
1114
import com.fasterxml.jackson.dataformat.ion.IonObjectMapper;
1215
import com.fasterxml.jackson.dataformat.ion.IonParser;
@@ -73,7 +76,8 @@ static class IonValueData extends Data<IonValue> {
7376
}
7477

7578
private static final IonSystem SYSTEM = IonSystemBuilder.standard().build();
76-
private final IonValueMapper ION_VALUE_MAPPER = new IonValueMapper(SYSTEM, SNAKE_CASE);
79+
private static final IonValueMapper ION_VALUE_MAPPER = new IonValueMapper(SYSTEM, SNAKE_CASE);
80+
private static final IonValueMapper ION_MAPPER_READ_NULL_DISABLED = (IonValueMapper) new IonValueMapper(SYSTEM, SNAKE_CASE).disable(IonParser.Feature.READ_NULL_AS_IONVALUE);
7781

7882
@Test
7983
public void shouldBeAbleToDeserialize() throws Exception {
@@ -101,45 +105,43 @@ public void shouldBeAbleToDeserializeIncludingNullList() throws Exception {
101105

102106
@Test
103107
public void shouldBeAbleToDeserializeNullToIonNull() throws Exception {
104-
String ion = "{c:null}";
105-
verifyNullDeserialization(ion, SYSTEM.newNull());
106-
ION_VALUE_MAPPER.disable(IonParser.Feature.READ_NULL_AS_IONVALUE);
107-
verifyNullDeserialization(ion, null);
108+
verifyNullDeserialization("{c:null}", SYSTEM.newNull(), null);
108109
}
109110

110111
@Test
111112
public void shouldBeAbleToDeserializeNullList() throws Exception {
112-
String ion = "{c:null.list}";
113-
verifyNullDeserialization(ion, SYSTEM.newNullList());
114-
ION_VALUE_MAPPER.disable(IonParser.Feature.READ_NULL_AS_IONVALUE);
115-
verifyNullDeserialization(ion, SYSTEM.newNullList());
113+
verifyNullDeserialization("{c:null.list}", SYSTEM.newNullList());
116114
}
117115

116+
117+
118118
@Test
119119
public void shouldBeAbleToDeserializeNullStruct() throws Exception {
120-
String ion = "{c:null.struct}";
121-
verifyNullDeserialization(ion, SYSTEM.newNullStruct());
122-
ION_VALUE_MAPPER.disable(IonParser.Feature.READ_NULL_AS_IONVALUE);
123-
verifyNullDeserialization(ion, SYSTEM.newNullStruct());
120+
verifyNullDeserialization("{c:null.struct}", SYSTEM.newNullStruct());
124121
}
125122

126123
@Test
127124
public void shouldBeAbleToDeserializeNullSexp() throws Exception {
128-
String ion = "{c:null.sexp}";
129-
verifyNullDeserialization(ion, SYSTEM.newNullSexp());
130-
ION_VALUE_MAPPER.disable(IonParser.Feature.READ_NULL_AS_IONVALUE);
131-
verifyNullDeserialization(ion, SYSTEM.newNullSexp());
125+
verifyNullDeserialization("{c:null.sexp}", SYSTEM.newNullSexp());
132126
}
133127

134128
private void verifyNullDeserialization(String ionString, IonValue expected) throws Exception {
129+
verifyNullDeserialization(ionString, expected, expected);
130+
}
131+
132+
private void verifyNullDeserialization(String ionString, IonValue expected, IonValue expectedReadNullDisabled) throws Exception {
133+
verifyNullDeserialization(ION_VALUE_MAPPER, ionString, expected);
134+
verifyNullDeserialization(ION_MAPPER_READ_NULL_DISABLED, ionString, expectedReadNullDisabled);
135+
}
135136

136-
IonValueData data = ION_VALUE_MAPPER.readValue(ionString, IonValueData.class);
137+
private void verifyNullDeserialization(IonValueMapper mapper, String ionString, IonValue expected) throws Exception {
138+
IonValueData data = mapper.readValue(ionString, IonValueData.class);
137139

138140
assertEquals(1, data.getAllData().size());
139141
assertEquals(expected, data.getAllData().get("c"));
140142

141143
IonValue ion = ion(ionString);
142-
data = ION_VALUE_MAPPER.readValue(ion, IonValueData.class);
144+
data = mapper.readValue(ion, IonValueData.class);
143145

144146
assertEquals(1, data.getAllData().size());
145147
assertEquals(expected, data.getAllData().get("c"));
@@ -188,6 +190,22 @@ public void shouldBeAbleToSerializeAndDeserializePojo() throws Exception {
188190
assertEquals(source, result);
189191
}
190192

193+
@Test
194+
public void shouldBeAbleToSerializeAndDeserializeIonValueDataWithIncludeNonNull() throws Exception {
195+
IonValueData source = new IonValueData();
196+
source.put("a", SYSTEM.newInt(1));
197+
source.put("b", SYSTEM.newNull());
198+
source.put("c", null);
199+
IonValueMapper mapper = (IonValueMapper) ION_VALUE_MAPPER.copy().setSerializationInclusion(JsonInclude.Include.NON_NULL);
200+
201+
String data = mapper.writeValueAsString(source);
202+
assertEquals("{a:1,b:null}", data);
203+
// Now remove the null element for the comparison below.
204+
source.getAllData().remove("c");
205+
IonValueData result = mapper.readValue(data, IonValueData.class);
206+
assertEquals(source, result);
207+
}
208+
191209
@Test
192210
public void shouldBeAbleToSerializeAndDeserializeStringData() throws Exception {
193211
StringData source = new StringData();

0 commit comments

Comments
 (0)