Skip to content

Commit ea4527d

Browse files
Add support for deserializing IonTimestamps and IonBlobs (#244)
1 parent f6ec934 commit ea4527d

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

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

+4
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ public Version version() {
159159
return PackageVersion.VERSION;
160160
}
161161

162+
public IonSystem getIonSystem() {
163+
return _system;
164+
}
165+
162166
/*
163167
/**********************************************************
164168
/* Capability introspection

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

+24-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@
1818

1919
import com.fasterxml.jackson.core.JsonParser;
2020
import com.fasterxml.jackson.databind.DeserializationContext;
21+
import com.fasterxml.jackson.databind.JsonMappingException;
2122
import com.fasterxml.jackson.databind.JsonDeserializer;
23+
import com.fasterxml.jackson.dataformat.ion.IonParser;
24+
import com.amazon.ion.IonSystem;
2225
import com.amazon.ion.IonValue;
26+
import com.amazon.ion.Timestamp;
2327

2428
/**
2529
* Deserializer that knows how to deserialize an IonValue.
@@ -28,6 +32,25 @@ class IonValueDeserializer extends JsonDeserializer<IonValue> {
2832

2933
@Override
3034
public IonValue deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
31-
return (IonValue) jp.getEmbeddedObject();
35+
Object embeddedObject = jp.getEmbeddedObject();
36+
if (embeddedObject instanceof IonValue) {
37+
return (IonValue) embeddedObject;
38+
}
39+
// We rely on the IonParser's IonSystem to wrap supported types into an IonValue
40+
if (!(jp instanceof IonParser)) {
41+
throw JsonMappingException.from(jp, "Unsupported parser for deserializing "
42+
+ embeddedObject.getClass().getCanonicalName() + " into IonValue");
43+
}
44+
45+
IonSystem ionSystem = ((IonParser) jp).getIonSystem();
46+
if (embeddedObject instanceof Timestamp) {
47+
return ionSystem.newTimestamp((Timestamp) embeddedObject);
48+
}
49+
if (embeddedObject instanceof byte[]) {
50+
// The parser provides no distinction between BLOB and CLOB, deserializing to a BLOB is the safest choice.
51+
return ionSystem.newBlob((byte[]) embeddedObject);
52+
}
53+
throw JsonMappingException.from(jp, "Cannot deserialize embedded object type "
54+
+ embeddedObject.getClass().getCanonicalName() + " into IonValue");
3255
}
3356
}

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

+36
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,38 @@ public void testPojo2() throws Exception {
128128
assertRoundTrip(value, TestPojo2.class);
129129
}
130130

131+
@Test
132+
public void testPojo2WithTimestamp() throws Exception {
133+
String value = "{" +
134+
"raw_value:2017-05-25T15:33:08Z," +
135+
"raw_sexp:(this that)," +
136+
"wrapped_sexp:{sexp:(other)}," +
137+
"}";
138+
139+
TestPojo2 t = ionValueMapper.parse(ionSystem.singleValue(value), TestPojo2.class);
140+
assertEquals(ionSystem.singleValue("2017-05-25T15:33:08Z"), t.rawValue);
141+
assertEquals(ionSystem.singleValue("(this that)"), t.rawSexp);
142+
assertEquals(ionSystem.singleValue("(other)"), t.wrappedSexp.sexp);
143+
144+
assertRoundTrip(value, TestPojo2.class);
145+
}
146+
147+
@Test
148+
public void testPojo2WithBlob() throws Exception {
149+
String value = "{" +
150+
"raw_value:{{YmxvYl92YWx1ZQ==}}," +
151+
"raw_sexp:(this that)," +
152+
"wrapped_sexp:{sexp:(other)}," +
153+
"}";
154+
155+
TestPojo2 t = ionValueMapper.parse(ionSystem.singleValue(value), TestPojo2.class);
156+
assertEquals(ionSystem.newBlob("blob_value".getBytes()), t.rawValue);
157+
assertEquals(ionSystem.singleValue("(this that)"), t.rawSexp);
158+
assertEquals(ionSystem.singleValue("(other)"), t.wrappedSexp.sexp);
159+
160+
assertRoundTrip(value, TestPojo2.class);
161+
}
162+
131163
/**
132164
* This Pojo supports open content
133165
*/
@@ -154,12 +186,16 @@ public void testPojo3WithOpenContent() throws Exception {
154186
"expected:1," +
155187
"something_unexpected:(boo!)," +
156188
"another_random_struct:{yikes:scared}," +
189+
"timestamp_att:2021-02-15T18:40:40Z," +
190+
"blob_att:{{YmxvYl92YWx1ZQ==}}," +
157191
"}";
158192

159193
TestPojo3 t = ionValueMapper.parse(ionSystem.singleValue(value), TestPojo3.class);
160194
assertEquals(1, t.expected);
161195
assertEquals(ionSystem.singleValue("(boo!)"), t.any().get("something_unexpected"));
162196
assertEquals(ionSystem.singleValue("{yikes:scared}"), t.any().get("another_random_struct"));
197+
assertEquals(ionSystem.singleValue("2021-02-15T18:40:40Z"), t.any().get("timestamp_att"));
198+
assertEquals(ionSystem.newBlob("blob_value".getBytes()), t.any().get("blob_att"));
163199

164200
assertRoundTrip(value, TestPojo3.class);
165201
}

0 commit comments

Comments
 (0)