Skip to content

Commit

Permalink
Add StreamReadCapability.EXACT_FLOATS to signal potential precision l…
Browse files Browse the repository at this point in the history
…oss for JSON non-doubles. (#733)
  • Loading branch information
htmldoug authored Jan 3, 2022
1 parent 6f810ea commit e655e46
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/main/java/com/fasterxml/jackson/core/StreamReadCapability.java
Original file line number Diff line number Diff line change
Expand Up @@ -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)
;

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}

}

0 comments on commit e655e46

Please sign in to comment.