FasterXML / FasterXML/jackson-dataformats-binary
Missing "null" default values when generating schema
- 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.