diff --git a/src/main/java/com/fasterxml/jackson/core/StreamReadCapability.java b/src/main/java/com/fasterxml/jackson/core/StreamReadCapability.java index 63d8b50282..5519e2be37 100644 --- a/src/main/java/com/fasterxml/jackson/core/StreamReadCapability.java +++ b/src/main/java/com/fasterxml/jackson/core/StreamReadCapability.java @@ -48,6 +48,23 @@ public enum StreamReadCapability * This capability is true for many textual formats like CSV, Properties and XML. */ UNTYPED_SCALARS(false), + + /** + * Capability that indicates that data format may report floats + * as a non-exact {@link com.fasterxml.jackson.core.JsonParser.NumberType}, + * due to prohibitively expensive parsing costs of determing the precision + * upfront. For example, JSON numbers may be reported as + * {@link com.fasterxml.jackson.core.JsonParser.NumberType#DOUBLE} + * even if they would not fit into a 64-bit double without precision + * loss. Methods like {@link JsonParser#getNumberValueExact()} or + * {@link JsonParser#getValueAsString()} still report values without + * precision loss. + * + * Capability is false for text formats JSON, but true for binary formats + * like Smile, MessagePack, etc., where type is precisely and inexpensively + * signaled by a tag. + */ + EXACT_FLOATS(false) ; /** diff --git a/src/test/java/com/fasterxml/jackson/failing/ParserPrecisionLoss733Test.java b/src/test/java/com/fasterxml/jackson/failing/ParserPrecisionLoss733Test.java new file mode 100644 index 0000000000..fd39060fc8 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/failing/ParserPrecisionLoss733Test.java @@ -0,0 +1,47 @@ +package com.fasterxml.jackson.failing; + +import com.fasterxml.jackson.core.BaseTest; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; + +import java.io.ByteArrayOutputStream; +import java.io.StringWriter; + +public class ParserPrecisionLoss733Test extends BaseTest { + final JsonFactory JSON_F = newStreamFactory(); + + /** + * Attempt to pass a BigDecimal value through without losing precision, + * e.g. for pretty printing a file. + */ + public void testCopyCurrentEventBigDecimal() throws Exception { + String input = "1e999"; + JsonParser parser = JSON_F.createParser(input); + parser.nextToken(); + StringWriter stringWriter = new StringWriter(); + JsonGenerator generator = JSON_F.createGenerator(stringWriter); + generator.copyCurrentEvent(parser); + parser.close(); + generator.close(); + String actual = stringWriter.toString(); + assertEquals(input, actual); + } + + /** + * Same as {@link #testCopyCurrentEventBigDecimal()} using copyCurrentStructure instead. + */ + public void testCopyCurrentStructureBigDecimal() throws Exception { + String input = "[1e999]"; + JsonParser parser = JSON_F.createParser(input); + parser.nextToken(); + StringWriter stringWriter = new StringWriter(); + JsonGenerator generator = JSON_F.createGenerator(stringWriter); + generator.copyCurrentStructure(parser); + parser.close(); + generator.close(); + String actual = stringWriter.toString(); + assertEquals(input, actual); + } + +}