Skip to content

Commit

Permalink
AVRO-2885: better check int vs float value
Browse files Browse the repository at this point in the history
  • Loading branch information
clesaec committed Jul 28, 2023
1 parent f033de6 commit ecd20be
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 8 deletions.
30 changes: 22 additions & 8 deletions lang/java/avro/src/main/java/org/apache/avro/io/JsonDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ private static Symbol getSymbol(Schema schema) {
* <p/>
* Otherwise, this JsonDecoder will reset its state and then reconfigure its
* input.
*
*
* @param in The InputStream to read from. Cannot be null.
* @throws IOException
* @throws NullPointerException if {@code in} is {@code null}
Expand All @@ -109,7 +109,7 @@ public JsonDecoder configure(InputStream in) throws IOException {
* <p/>
* Otherwise, this JsonDecoder will reset its state and then reconfigure its
* input.
*
*
* @param in The String to read from. Cannot be null.
* @throws IOException
* @throws NullPointerException if {@code in} is {@code null}
Expand Down Expand Up @@ -157,25 +157,39 @@ public boolean readBoolean() throws IOException {
@Override
public int readInt() throws IOException {
advance(Symbol.INT);
if (in.getCurrentToken().isNumeric()) {
if (in.getCurrentToken() == JsonToken.VALUE_NUMBER_INT) {
int result = in.getIntValue();
in.nextToken();
return result;
} else {
throw error("int");
}
if (in.getCurrentToken() == JsonToken.VALUE_NUMBER_FLOAT) {
float value = in.getFloatValue();
if (Math.abs(value - Math.round(value)) <= Float.MIN_VALUE) {
int result = Math.round(value);
in.nextToken();
return result;
}
}
throw error("int");
}

@Override
public long readLong() throws IOException {
advance(Symbol.LONG);
if (in.getCurrentToken().isNumeric()) {
if (in.getCurrentToken() == JsonToken.VALUE_NUMBER_INT) {
long result = in.getLongValue();
in.nextToken();
return result;
} else {
throw error("long");
}
if (in.getCurrentToken() == JsonToken.VALUE_NUMBER_FLOAT) {
double value = in.getDoubleValue();
if (Math.abs(value - Math.round(value)) <= Double.MIN_VALUE) {
long result = Math.round(value);
in.nextToken();
return result;
}
}
throw error("long");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.apache.avro.AvroTypeException;
import org.apache.avro.Schema;
import org.apache.avro.SchemaBuilder;
import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.generic.GenericRecord;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.io.IOException;

public class TestJsonDecoder {

@Test
Expand Down Expand Up @@ -76,4 +82,14 @@ void reorderFields() throws Exception {
assertEquals(200, in.readLong());
in.skipArray();
}

@Test
void testIntWithError() throws IOException {
Schema schema = SchemaBuilder.builder("test").record("example").fields().requiredInt("id").endRecord();
String record = "{ \"id\": -1.2 }";

GenericDatumReader<GenericRecord> reader = new GenericDatumReader<>(schema, schema);
JsonDecoder decoder = DecoderFactory.get().jsonDecoder(schema, record);
Assertions.assertThrows(AvroTypeException.class, () -> reader.read(null, decoder));
}
}

0 comments on commit ecd20be

Please sign in to comment.