Skip to content

Commit

Permalink
refactor(avro schema): Avro Union + tests + default for Map and Array
Browse files Browse the repository at this point in the history
  • Loading branch information
Pakisan committed Apr 16, 2024
1 parent 2dc488e commit 87e7d32
Show file tree
Hide file tree
Showing 7 changed files with 278 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
property = "type",
defaultImpl = AvroUnion.class,
visible = true
)
@JsonSubTypes({
Expand Down Expand Up @@ -65,6 +66,9 @@ public enum LogicalType {
@JsonProperty("decimal")
DECIMAL,

@JsonProperty("big-decimal")
BIG_DECIMAL,

@JsonProperty("uuid")
UUID,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;

/**
* @see <a href="https://avro.apache.org/docs/1.9.0/spec.html#Arrays">Arrays</a>
Expand All @@ -19,19 +22,30 @@ public AvroArray() {
super(AvroType.ARRAY);
}

public AvroArray(@NotNull Object items) {
super(AvroType.ARRAY);
this.items = items;
}

@Builder(builderMethodName = "arrayBuilder")
public AvroArray(
@NotNull Object items
@NotNull Object items,
@Nullable List<Object> defaultValue
) {
super(AvroType.ARRAY);
this.items = items;
this.defaultValue = defaultValue;
}

@NotNull
@JsonProperty("items")
@JsonDeserialize(using = AvroTypeDeserializer.class)
private Object items;

@Nullable
@JsonProperty("default")
private List<Object> defaultValue;

@NotNull
@Override
public AvroType getType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@ public AvroMap(@NotNull Object values) {
}

@Builder(builderMethodName = "mapBuilder")
public AvroMap(@NotNull Object values, @Nullable Map<String, Object> metadata) {
public AvroMap(
@NotNull Object values,
@Nullable Map<String, Object> defaultValue,
@Nullable Map<String, Object> metadata
) {
this.values = values;
this.defaultValue = defaultValue;
this.metadata = metadata;
}

Expand All @@ -37,6 +42,10 @@ public AvroMap(@NotNull Object values, @Nullable Map<String, Object> metadata) {
@JsonDeserialize(using = AvroTypeDeserializer.class)
private Object values;

@Nullable
@JsonProperty("default")
private Map<String, Object> defaultValue;

@NotNull
@Override
public AvroType getType() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.asyncapi.v3.schema.avro.v1._9_0;

import com.asyncapi.v3.schema.avro.v1._9_0.jackson.AvroTypeDeserializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import org.jetbrains.annotations.NotNull;

import java.util.LinkedList;

/**
* Avro Union.
* <p>
* Unions, as mentioned above, are represented using JSON arrays.
* <p>
* For example, ["null", "string"] declares a schema which may be either a null or string.
* <p>
* <p>
* Note that when a default value is specified for a record field whose type is a union,
* the type of the default value must match the first element of the union.
* <p>
* Thus, for unions containing "null", the "null" is usually listed first,
* since the default value of such unions is typically null.
* <p>
* <p>
* Unions may not contain more than one schema with the same type, except for the named types record, fixed and enum.
* <p>
* For example, unions containing two array types or two map types are not permitted, but two types with different names are permitted.
* <p>
* (Names permit efficient resolution when reading and writing unions.)
* <p>
* Unions may not immediately contain other unions.
*
* @see <a href="https://avro.apache.org/docs/1.9.0/spec.html#Unions">Unions</a>
* @see <a href="https://avro.apache.org/docs/1.9.0/spec.html#schema_record">Record</a>
*/
@JsonDeserialize(contentUsing = AvroTypeDeserializer.class)
public class AvroUnion extends LinkedList<Object> {

public AvroUnion() {
super();
}

public AvroUnion(@NotNull Object variantA, @NotNull Object variantB) {
super();
add(0, variantA);
add(1, variantB);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.asyncapi.v3.schema.avro.v1._9_0.Avro;
import com.asyncapi.v3.schema.avro.v1._9_0.AvroType;
import com.asyncapi.v3.schema.avro.v1._9_0.AvroUnion;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
Expand All @@ -12,8 +13,6 @@
import com.fasterxml.jackson.databind.node.JsonNodeType;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class AvroTypeDeserializer extends JsonDeserializer<Object> {

Expand All @@ -31,7 +30,7 @@ private Object chooseKnownPojo(JsonNode jsonNode, final ObjectCodec objectCodec)

switch (nodeType) {
case ARRAY:
return readAsList((ArrayNode) jsonNode, objectCodec);
return readAsUnion((ArrayNode) jsonNode, objectCodec);
case BOOLEAN:
return jsonNode.asBoolean();
case NUMBER:
Expand All @@ -51,13 +50,13 @@ private Object chooseKnownPojo(JsonNode jsonNode, final ObjectCodec objectCodec)
}
}

private List<Object> readAsList(ArrayNode arrayNode, ObjectCodec objectCodec) throws IOException {
List<Object> list = new ArrayList<>();
private AvroUnion readAsUnion(ArrayNode arrayNode, ObjectCodec objectCodec) throws IOException {
AvroUnion avroUnion = new AvroUnion();
for (JsonNode childNode : arrayNode) {
list.add(chooseKnownPojo(childNode, objectCodec));
avroUnion.add(chooseKnownPojo(childNode, objectCodec));
}

return list;
return avroUnion;
}

}
Loading

0 comments on commit 87e7d32

Please sign in to comment.