Skip to content

Commit 0e8594b

Browse files
committed
Merge branch '3.1' into 3.2
2 parents 550ce76 + 503dfca commit 0e8594b

9 files changed

Lines changed: 514 additions & 198 deletions

File tree

avro/src/main/java/tools/jackson/dataformat/avro/deser/AvroFieldDefaulters.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ public static AvroFieldReader createDefaulter(String name,
3131
case VALUE_NUMBER_INT:
3232
switch (defaultAsNode.numberType()) {
3333
case INT:
34-
return new ScalarDefaults.FloatDefaults(name, defaultAsNode.asInt());
34+
return new ScalarDefaults.IntDefaults(name, defaultAsNode.asInt());
3535
case BIG_INTEGER: // TODO: maybe support separately?
3636
case LONG:
3737
default:
38-
return new ScalarDefaults.FloatDefaults(name, defaultAsNode.asLong());
38+
return new ScalarDefaults.LongDefaults(name, defaultAsNode.asLong());
3939
}
4040
case VALUE_STRING:
4141
return new ScalarDefaults.StringDefaults(name, defaultAsNode.asString());

avro/src/main/java/tools/jackson/dataformat/avro/ser/AvroWriteContext.java

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.math.BigDecimal;
55
import java.util.*;
66

7+
import org.apache.avro.LogicalTypes;
78
import org.apache.avro.Schema;
89
import org.apache.avro.Schema.Type;
910
import org.apache.avro.UnresolvedUnionException;
@@ -164,6 +165,7 @@ protected GenericRecord _createRecord(Schema schema, Object currValue)
164165
// couldn't find an exact match
165166
schema = _recordOrMapFromUnion(schema);
166167
}
168+
type = schema.getType();
167169
}
168170
if (type == Schema.Type.MAP) {
169171
throw new IllegalStateException("_createRecord should never be called for elements of type MAP");
@@ -182,6 +184,7 @@ protected GenericRecord _createRecord(Schema schema)
182184
Type type = schema.getType();
183185
if (type == Schema.Type.UNION) {
184186
schema = _recordOrMapFromUnion(schema);
187+
type = schema.getType();
185188
}
186189
if (type == Schema.Type.MAP) {
187190
throw new IllegalStateException("_createRecord should never be called for elements of type MAP");
@@ -432,25 +435,41 @@ private static int _findNotNullIndex(List<Schema> types)
432435

433436
private static int _resolveBigDecimalIndex(Schema unionSchema, List<Schema> types,
434437
BigDecimal value) {
435-
int match = -1;
438+
// Branches are considered in order of how well they retain the value,
439+
// regardless of declaration order: "decimal" first, then String, then Double
440+
int stringMatch = -1;
441+
int doubleMatch = -1;
436442

437443
for (int i = 0, size = types.size(); i < size; ++i) {
438444
Schema schema = types.get(i);
439445
Schema.Type t = schema.getType();
440446

441-
if (t == Type.DOUBLE) {
442-
return i;
443-
}
444-
// BigDecimals can be shoved into a double, but optimally would be a String or byte[] with logical type information
445-
if (t == Type.DOUBLE) {
446-
match = i;
447-
continue;
447+
if (t == Type.BYTES || t == Type.FIXED) {
448+
// Best match: retains both scale and type.
449+
// NOTE: plain `bytes`/`fixed` must NOT be chosen, since conversion
450+
// requires the "decimal" logical type to exist
451+
if (schema.getLogicalType() instanceof LogicalTypes.Decimal) {
452+
return i;
453+
}
454+
} else if (t == Type.STRING) {
455+
// Second best: retains all digits, but reads back as String
456+
if (stringMatch < 0) {
457+
stringMatch = i;
458+
}
459+
} else if (t == Type.DOUBLE) {
460+
// Last resort: lossy
461+
if (doubleMatch < 0) {
462+
doubleMatch = i;
463+
}
448464
}
449465
}
450-
if (match < 0) {
451-
match = ReflectData.get().resolveUnion(unionSchema, value);
466+
if (stringMatch >= 0) {
467+
return stringMatch;
452468
}
453-
return match;
469+
if (doubleMatch >= 0) {
470+
return doubleMatch;
471+
}
472+
return ReflectData.get().resolveUnion(unionSchema, value);
454473
}
455474

456475
private static int _resolveMapIndex(Schema unionSchema, List<Schema> types,

avro/src/main/java/tools/jackson/dataformat/avro/ser/RootContext.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,17 @@ public final AvroWriteContext createChildObjectContext(Object currValue) {
5959
// verify that root type is record (or compatible)
6060
switch (_schema.getType()) {
6161
case RECORD:
62-
case UNION: // maybe
6362
{
6463
GenericRecord rec = _createRecord(_schema, currValue);
6564
_rootValue = rec;
6665
return new ObjectWriteContext(this, _generator, rec, currValue);
6766
}
67+
case UNION: // maybe: may resolve to either Record or Map
68+
{
69+
AvroWriteContext child = _createObjectContext(_schema, currValue);
70+
_rootValue = child.rawValue();
71+
return child;
72+
}
6873
case MAP: // used to not be supported
6974
{
7075
MapWriteContext ctxt = new MapWriteContext(this, _generator, _schema, currValue);

0 commit comments

Comments
 (0)