FasterXML / FasterXML/jackson-dataformats-binary

Missing "null" default values when generating schema

Open
#207 10 comments 1 reaction 0 assignees View on GitHub
avro
Dominant language
Java
Stars
347
Forks
156
Avg merge
3d 3h
Merged PRs (30d)
22

Description

After upgrading from jackson `2.10.3` to `2.11.0` and using avro `1.9.2`, I noticed that the schema generation is broken regarding default "null" values for union types.

Exemple POJO :

```
public class Book {

@JsonProperty(defaultValue = "null")
private String title;

public Book() {
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

}
```

Code to generate the JSON schema :

```
AvroMapper mapper = new AvroMapper(new AvroFactory());
com.fasterxml.jackson.dataformat.avro.schema.AvroSchemaGenerator gen = new com.fasterxml.jackson.dataformat.avro.schema.AvroSchemaGenerator();
mapper.acceptJsonFormatVisitor(Book.class, gen);
AvroSchema schemaWrapper = gen.getGeneratedSchema();
org.apache.avro.Schema schema = schemaWrapper.getAvroSchema();
System.out.println(schema.toString(true));
```

With version 2.10.3 we had :

```
{
"type": "record",
"name": "Book",
"namespace": "com.example",
"fields": [
{
"name": "title",
"type": [
"null",
"string"
],
"default": null
}
]
}
```

Now with version 2.11.0 we have :

```
{
"type": "record",
"name": "Book",
"namespace": "com.example",
"fields": [
{
"name": "title",
"type": [
"null",
"string"
]
}
]
}
```

The `default` field in the schema is missing when generating the schema with version `2.11.0`

After short analysis, I have noticed than in the `org.apache.avro` class, the method `hasDefaultValue` always returns `false`, so when generating the json schema output in the `fieldsToJson` method, this code never write the default field :

```
if (f.hasDefaultValue()) {
gen.writeFieldName("default");
gen.writeTree(f.defaultValue());
}
```

The `Field` instance is instanciated by `com.fasterxml.jackson.dataformat.avro.schema.RecordVisitor` and it seems to mess up with the default value :

```

JsonNode defaultValue = AvroSchemaHelper.parseDefaultValue(prop.getMetadata().getDefaultValue());
writerSchema = this.reorderUnionToMatchDefaultType(writerSchema, defaultValue);
Field field = new Field(prop.getName(), writerSchema, prop.getMetadata().getDescription(), AvroSchemaHelper.jsonNodeToObject(defaultValue));
AvroMeta meta = (AvroMeta)prop.getAnnotation(AvroMeta.class);
if (meta != null) {
field.addProp(meta.key(), meta.value());
}
```

When debugging, with this `Book` class :
- `JsonNode defaultValue` contains an instance of `NullNode`
- `AvroSchemaHelper.jsonNodeToObject(defaultValue)` returns null
- in the `Field` constructor there is a weird comparison `defaultValue == NULL_DEFAULT_VALUE` where NULL_DEFAULT_VALUE = new Object()
- it results in the default `NullNode` default value being completely forgotten and replaced by null which results in no default value at all

Did something change to how I should specify a default value on a POJO field ?
I tried with @JsonProperty and @AvroDefault but none work.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.