Skip to content

Commit f5673da

Browse files
authored
Merge pull request #176 from marcospassos/fix-root-union-serialization-2.10
Fix serialization of union types at root level (fixes #168)
2 parents 1e27b2a + 6b2fd9c commit f5673da

File tree

9 files changed

+216
-71
lines changed

9 files changed

+216
-71
lines changed

avro/src/main/java/com/fasterxml/jackson/dataformat/avro/ser/ArrayWriteContext.java

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class ArrayWriteContext
1111
protected final GenericArray<Object> _array;
1212

1313
public ArrayWriteContext(AvroWriteContext parent, AvroGenerator generator,
14-
GenericArray<Object> array)
14+
GenericArray<Object> array, Object currValue)
1515
{
1616
super(TYPE_ARRAY, parent, generator, array.getSchema());
1717
_array = array;
@@ -21,23 +21,15 @@ public ArrayWriteContext(AvroWriteContext parent, AvroGenerator generator,
2121
public Object rawValue() { return _array; }
2222

2323
@Override
24-
public final AvroWriteContext createChildArrayContext() throws JsonMappingException {
24+
public final AvroWriteContext createChildArrayContext(Object currValue) throws JsonMappingException {
2525
GenericArray<Object> arr = _createArray(_schema.getElementType());
2626
_array.add(arr);
27-
return new ArrayWriteContext(this, _generator, arr);
27+
return new ArrayWriteContext(this, _generator, arr, currValue);
2828
}
2929

3030
@Override
31-
public final AvroWriteContext createChildObjectContext() throws JsonMappingException
32-
{
33-
AvroWriteContext child = _createObjectContext(_schema.getElementType());
34-
_array.add(child.rawValue());
35-
return child;
36-
}
37-
38-
@Override
39-
public AvroWriteContext createChildObjectContext(Object object) throws JsonMappingException {
40-
AvroWriteContext child = _createObjectContext(_schema.getElementType(), object);
31+
public AvroWriteContext createChildObjectContext(Object currValue) throws JsonMappingException {
32+
AvroWriteContext child = _createObjectContext(_schema.getElementType(), currValue);
4133
_array.add(child.rawValue());
4234
return child;
4335
}

avro/src/main/java/com/fasterxml/jackson/dataformat/avro/ser/AvroWriteContext.java

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,18 @@ protected AvroWriteContext(int type, AvroWriteContext parent,
5454
_generator = generator;
5555
_schema = schema;
5656
}
57-
57+
58+
protected AvroWriteContext(int type, AvroWriteContext parent,
59+
AvroGenerator generator, Schema schema, Object currValue)
60+
{
61+
super();
62+
_type = type;
63+
_parent = parent;
64+
_generator = generator;
65+
_schema = schema;
66+
_currentValue = currValue;
67+
}
68+
5869
// // // Factory methods
5970

6071
public static AvroWriteContext createRootContext(AvroGenerator generator, Schema schema,
@@ -70,15 +81,22 @@ public static AvroWriteContext nullContext() {
7081
return NullContext.instance;
7182
}
7283

73-
public abstract AvroWriteContext createChildArrayContext() throws JsonMappingException;
74-
public abstract AvroWriteContext createChildObjectContext() throws JsonMappingException;
84+
public final AvroWriteContext createChildArrayContext() throws JsonMappingException {
85+
return createChildArrayContext(null);
86+
}
87+
88+
public abstract AvroWriteContext createChildArrayContext(Object currValue) throws JsonMappingException;
89+
90+
public AvroWriteContext createChildObjectContext() throws JsonMappingException {
91+
return createChildObjectContext(null);
92+
}
93+
94+
public abstract AvroWriteContext createChildObjectContext(Object currValue) throws JsonMappingException;
7595

7696
public void complete() throws IOException {
7797
throw new IllegalStateException("Can not be called on "+getClass().getName());
7898
}
7999

80-
public AvroWriteContext createChildObjectContext(Object object) throws JsonMappingException { return createChildObjectContext(); }
81-
82100
/*
83101
/**********************************************************
84102
/* Accessors
@@ -154,6 +172,28 @@ public final String toString()
154172

155173
// // // Shared helper methods
156174

175+
protected GenericRecord _createRecord(Schema schema, Object currValue) throws JsonMappingException
176+
{
177+
Type type = schema.getType();
178+
if (type == Schema.Type.UNION) {
179+
try {
180+
schema = resolveUnionSchema(schema, currValue);
181+
} catch (UnresolvedUnionException e) {
182+
// couldn't find an exact match
183+
schema = _recordOrMapFromUnion(schema);
184+
}
185+
}
186+
if (type == Schema.Type.MAP) {
187+
throw new IllegalStateException("_createRecord should never be called for elements of type MAP");
188+
}
189+
try {
190+
return new GenericData.Record(schema);
191+
} catch (RuntimeException e) {
192+
// alas, generator not passed to us
193+
throw new JsonMappingException(null, "Failed to create Record type from "+type, e);
194+
}
195+
}
196+
157197
protected GenericRecord _createRecord(Schema schema) throws JsonMappingException
158198
{
159199
// Quick check: if type is Union, need to find actual record type...
@@ -191,22 +231,23 @@ protected AvroWriteContext _createObjectContext(Schema schema) throws JsonMappin
191231
return _createObjectContext(schema, null); // Object doesn't matter as long as schema isn't a union
192232
}
193233

194-
protected AvroWriteContext _createObjectContext(Schema schema, Object object) throws JsonMappingException
234+
protected AvroWriteContext _createObjectContext(Schema schema, Object currValue)
235+
throws JsonMappingException
195236
{
196237
Type type = schema.getType();
197238
if (type == Schema.Type.UNION) {
198239
try {
199-
schema = resolveUnionSchema(schema, object);
240+
schema = resolveUnionSchema(schema, currValue);
200241
} catch (UnresolvedUnionException e) {
201242
// couldn't find an exact match
202243
schema = _recordOrMapFromUnion(schema);
203244
}
204245
type = schema.getType();
205246
}
206247
if (type == Schema.Type.MAP) {
207-
return new MapWriteContext(this, _generator, schema);
248+
return new MapWriteContext(this, _generator, schema, currValue);
208249
}
209-
return new ObjectWriteContext(this, _generator, _createRecord(schema));
250+
return new ObjectWriteContext(this, _generator, _createRecord(schema), currValue);
210251
}
211252

212253
protected Schema _recordOrMapFromUnion(Schema unionSchema)
@@ -503,17 +544,17 @@ private NullContext() {
503544
public Object rawValue() { return null; }
504545

505546
@Override
506-
public final AvroWriteContext createChildArrayContext() {
547+
public final AvroWriteContext createChildArrayContext(Object currValue) {
507548
_reportError();
508549
return null;
509550
}
510-
551+
511552
@Override
512-
public final AvroWriteContext createChildObjectContext() {
553+
public final AvroWriteContext createChildObjectContext(Object currValue) {
513554
_reportError();
514555
return null;
515556
}
516-
557+
517558
@Override
518559
public void writeValue(Object value) {
519560
_reportError();

avro/src/main/java/com/fasterxml/jackson/dataformat/avro/ser/KeyValueContext.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ abstract class KeyValueContext extends AvroWriteContext
1414
protected boolean _expectValue = false;
1515

1616
protected KeyValueContext(AvroWriteContext parent, AvroGenerator generator,
17-
Schema schema)
17+
Schema schema, Object currValue)
1818
{
19-
super(TYPE_OBJECT, parent, generator, schema);
19+
super(TYPE_OBJECT, parent, generator, schema, currValue);
2020
}
2121

2222
@Override

avro/src/main/java/com/fasterxml/jackson/dataformat/avro/ser/MapWriteContext.java

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ public final class MapWriteContext
1717
{
1818
protected final Map<String,Object> _data;
1919

20-
public MapWriteContext(AvroWriteContext parent, AvroGenerator generator, Schema schema)
20+
public MapWriteContext(AvroWriteContext parent, AvroGenerator generator,
21+
Schema schema, Object currValue)
2122
{
22-
super(parent, generator, schema);
23+
super(parent, generator, schema, currValue);
2324
_data = new HashMap<String,Object>();
2425
}
2526

@@ -33,21 +34,12 @@ public final boolean writeFieldName(String name)
3334
_expectValue = true;
3435
return true;
3536
}
36-
37-
@Override
38-
public final AvroWriteContext createChildArrayContext() {
39-
_verifyValueWrite();
40-
AvroWriteContext child = new ArrayWriteContext(this, _generator,
41-
_createArray(_schema.getValueType()));
42-
_data.put(_currentName, child.rawValue());
43-
return child;
44-
}
4537

4638
@Override
47-
public final AvroWriteContext createChildObjectContext() throws JsonMappingException
48-
{
39+
public final AvroWriteContext createChildArrayContext(Object currValue) {
4940
_verifyValueWrite();
50-
AvroWriteContext child = _createObjectContext(_schema.getValueType());
41+
AvroWriteContext child = new ArrayWriteContext(this, _generator,
42+
_createArray(_schema.getValueType()), currValue);
5143
_data.put(_currentName, child.rawValue());
5244
return child;
5345
}

avro/src/main/java/com/fasterxml/jackson/dataformat/avro/ser/NopWriteContext.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,24 @@
88
*/
99
public class NopWriteContext extends AvroWriteContext
1010
{
11-
public NopWriteContext(int type, AvroWriteContext parent, AvroGenerator generator) {
12-
super(type, parent, generator, null);
11+
public NopWriteContext(int type, AvroWriteContext parent, AvroGenerator generator,
12+
Object currValue) {
13+
super(type, parent, generator, null, currValue);
1314
}
1415

1516
@Override
1617
public Object rawValue() { return null; }
1718

1819
@Override
19-
public final AvroWriteContext createChildArrayContext() throws JsonMappingException {
20-
return new NopWriteContext(TYPE_ARRAY, this, _generator);
20+
public final AvroWriteContext createChildArrayContext(Object currValue) throws JsonMappingException {
21+
return new NopWriteContext(TYPE_ARRAY, this, _generator, currValue);
2122
}
22-
23+
2324
@Override
24-
public final AvroWriteContext createChildObjectContext() throws JsonMappingException {
25-
return new NopWriteContext(TYPE_OBJECT, this, _generator);
25+
public final AvroWriteContext createChildObjectContext(Object currValue) throws JsonMappingException {
26+
return new NopWriteContext(TYPE_OBJECT, this, _generator, currValue);
2627
}
27-
28+
2829
@Override
2930
public void writeValue(Object value) { }
3031

avro/src/main/java/com/fasterxml/jackson/dataformat/avro/ser/ObjectWriteContext.java

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,49 +23,50 @@ public final class ObjectWriteContext
2323
protected Schema.Field _nextField;
2424

2525
public ObjectWriteContext(AvroWriteContext parent, AvroGenerator generator,
26-
GenericRecord record)
26+
GenericRecord record, Object currValue)
2727
{
28-
super(parent, generator, record.getSchema());
28+
super(parent, generator, record.getSchema(), currValue);
2929
_record = record;
3030
}
3131

3232
@Override
3333
public Object rawValue() { return _record; }
3434

35+
3536
@Override
36-
public final AvroWriteContext createChildArrayContext()
37+
public final AvroWriteContext createChildArrayContext(Object currValue)
3738
{
3839
_verifyValueWrite();
3940
Schema.Field field = _findField();
4041
if (field == null) { // unknown, to ignore
41-
return new NopWriteContext(TYPE_ARRAY, this, _generator);
42+
return new NopWriteContext(TYPE_ARRAY, this, _generator, currValue);
4243
}
43-
AvroWriteContext child = new ArrayWriteContext(this, _generator, _createArray(field.schema()));
44+
AvroWriteContext child = new ArrayWriteContext(this, _generator,
45+
_createArray(field.schema()), currValue);
4446
_record.put(_currentName, child.rawValue());
4547
return child;
4648
}
4749

4850
@Override
49-
public final AvroWriteContext createChildObjectContext() throws JsonMappingException
50-
{
51+
public AvroWriteContext createChildObjectContext() throws JsonMappingException {
5152
_verifyValueWrite();
5253
Schema.Field field = _findField();
5354
if (field == null) { // unknown, to ignore
54-
return new NopWriteContext(TYPE_OBJECT, this, _generator);
55+
return new NopWriteContext(TYPE_OBJECT, this, _generator, null);
5556
}
5657
AvroWriteContext child = _createObjectContext(field.schema());
5758
_record.put(_currentName, child.rawValue());
5859
return child;
5960
}
6061

6162
@Override
62-
public AvroWriteContext createChildObjectContext(Object object) throws JsonMappingException {
63+
public AvroWriteContext createChildObjectContext(Object currValue) throws JsonMappingException {
6364
_verifyValueWrite();
6465
Schema.Field field = _findField();
6566
if (field == null) { // unknown, to ignore
66-
return new NopWriteContext(TYPE_OBJECT, this, _generator);
67+
return new NopWriteContext(TYPE_OBJECT, this, _generator, currValue);
6768
}
68-
AvroWriteContext child = _createObjectContext(field.schema(), object);
69+
AvroWriteContext child = _createObjectContext(field.schema(), currValue);
6970
_record.put(_currentName, child.rawValue());
7071
return child;
7172
}

avro/src/main/java/com/fasterxml/jackson/dataformat/avro/ser/RootContext.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,9 @@ public RootContext(AvroGenerator generator, Schema schema, BinaryEncoder encoder
3838

3939
@Override
4040
public Object rawValue() { return _rootValue; }
41-
41+
4242
@Override
43-
public final AvroWriteContext createChildArrayContext() throws JsonMappingException
44-
{
43+
public final AvroWriteContext createChildArrayContext(Object currValue) throws JsonMappingException {
4544
// verify that root type is array (or compatible)
4645
switch (_schema.getType()) {
4746
case ARRAY:
@@ -53,24 +52,23 @@ public final AvroWriteContext createChildArrayContext() throws JsonMappingExcept
5352
}
5453
GenericArray<Object> arr = _createArray(_schema);
5554
_rootValue = arr;
56-
return new ArrayWriteContext(this, _generator, arr);
55+
return new ArrayWriteContext(this, _generator, arr, currValue);
5756
}
58-
57+
5958
@Override
60-
public final AvroWriteContext createChildObjectContext() throws JsonMappingException
61-
{
59+
public final AvroWriteContext createChildObjectContext(Object currValue) throws JsonMappingException {
6260
// verify that root type is record (or compatible)
6361
switch (_schema.getType()) {
6462
case RECORD:
6563
case UNION: // maybe
6664
{
67-
GenericRecord rec = _createRecord(_schema);
65+
GenericRecord rec = _createRecord(_schema, currValue);
6866
_rootValue = rec;
69-
return new ObjectWriteContext(this, _generator, rec);
67+
return new ObjectWriteContext(this, _generator, rec, currValue);
7068
}
7169
case MAP: // used to not be supported
7270
{
73-
MapWriteContext ctxt = new MapWriteContext(this, _generator, _schema);
71+
MapWriteContext ctxt = new MapWriteContext(this, _generator, _schema, currValue);
7472
_rootValue = ctxt.rawValue();
7573
return ctxt;
7674
}

0 commit comments

Comments
 (0)