diff --git a/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java b/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java index 6245729bd..23a831b3e 100644 --- a/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java +++ b/cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORParser.java @@ -754,6 +754,9 @@ public JsonToken nextToken() throws IOException return (_currToken = JsonToken.VALUE_TRUE); case 22: return (_currToken = JsonToken.VALUE_NULL); + case 23: + return (_currToken = _decodeUndefinedValue()); + case 25: // 16-bit float... // As per [http://stackoverflow.com/questions/5678432/decompressing-half-precision-floats-in-javascript] { @@ -1229,6 +1232,10 @@ public String nextTextValue() throws IOException case 22: _currToken = JsonToken.VALUE_NULL; return null; + case 23: + _currToken = _decodeUndefinedValue(); + return null; + case 25: // 16-bit float... // As per [http://stackoverflow.com/questions/5678432/decompressing-half-precision-floats-in-javascript] { @@ -2888,6 +2895,20 @@ private final static long _long(int i1, int i2) return (l1 << 32) + l2; } + /** + * Helper method to encapsulate details of handling of mysterious `undefined` value + * that is allowed to be used as something encoder could not handle (as per spec), + * whatever the heck that should be. + * Current definition for 2.9 is that we will be return {@link JsonToken#VALUE_NULL}, but + * for later versions it is likely that we will alternatively allow decoding as + * {@link JsonToken#VALUE_EMBEDDED_OBJECT} with "embedded value" of `null`. + * + * @since 2.9.6 + */ + protected JsonToken _decodeUndefinedValue() throws IOException { + return JsonToken.VALUE_NULL; + } + /* /********************************************************** /* Internal methods, UTF8 decoding diff --git a/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/UndefinedValueTest.java b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/UndefinedValueTest.java new file mode 100644 index 000000000..d39d79fd7 --- /dev/null +++ b/cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/UndefinedValueTest.java @@ -0,0 +1,64 @@ +package com.fasterxml.jackson.dataformat.cbor.parse; + +import java.io.ByteArrayOutputStream; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.dataformat.cbor.CBORConstants; +import com.fasterxml.jackson.dataformat.cbor.CBORFactory; +import com.fasterxml.jackson.dataformat.cbor.CBORGenerator; +import com.fasterxml.jackson.dataformat.cbor.CBORTestBase; + +// for [dataformat-binary#93] +public class UndefinedValueTest extends CBORTestBase +{ + private final static byte BYTE_UNDEFINED = (byte) 0xF7; + + private final CBORFactory CBOR_F = cborFactory(); + + public void testUndefinedLiteralStreaming() throws Exception + { + JsonParser p = cborParser(CBOR_F, new byte[] { BYTE_UNDEFINED }); + assertEquals(JsonToken.VALUE_NULL, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } + + public void testUndefinedInArray() throws Exception + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + out.write(CBORConstants.BYTE_ARRAY_INDEFINITE); + out.write(BYTE_UNDEFINED); + out.write(CBORConstants.BYTE_BREAK); + JsonParser p = cborParser(CBOR_F, out.toByteArray()); + assertEquals(JsonToken.START_ARRAY, p.nextToken()); + assertEquals(JsonToken.VALUE_NULL, p.nextToken()); + assertEquals(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } + + public void testUndefinedInObject() throws Exception + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + CBORGenerator g = cborGenerator(out); + g.writeStartObject(); + g.writeFieldName("bar"); + g.writeBoolean(true); + g.writeEndObject(); + g.close(); + + byte[] doc = out.toByteArray(); + // assume we use end marker for Object, so + doc[doc.length-2] = BYTE_UNDEFINED; + + JsonParser p = cborParser(CBOR_F, doc); + assertEquals(JsonToken.START_OBJECT, p.nextToken()); + assertEquals(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("bar", p.currentName()); + assertEquals(JsonToken.VALUE_NULL, p.nextToken()); + assertEquals(JsonToken.END_OBJECT, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } +} diff --git a/release-notes/VERSION b/release-notes/VERSION index ec8839fb6..3df39641c 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -1,5 +1,4 @@ -Project: jackson-datatypes-binary -Modules: +Project: jackson-datatypes-binaryModules: jackson-dataformat-avro jackson-dataformat-cbor jackson-dataformat-protobuf @@ -11,6 +10,8 @@ Modules: 2.9.6 (not yet released) +#93: (cbor) `CBORParser` does not accept "undefined value" + (reported by mbaril@github) #135: (protobuf) Infinite sequence of `END_OBJECT` tokens returned at end of streaming read (reported by Leo W) #136: (avro) Fix MapWriteContext not correctly resolving union values