Skip to content

Commit 0dc16d7

Browse files
committed
JSON Schema to Avro: implement record writing
Signed-off-by: Francis Galiegue <[email protected]>
1 parent fc25186 commit 0dc16d7

File tree

5 files changed

+134
-0
lines changed

5 files changed

+134
-0
lines changed

src/main/java/com/github/fge/jsonschema2avro/AvroWriterProcessor.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.github.fge.jsonschema2avro.writers.ArrayWriter;
1515
import com.github.fge.jsonschema2avro.writers.EnumWriter;
1616
import com.github.fge.jsonschema2avro.writers.MapWriter;
17+
import com.github.fge.jsonschema2avro.writers.RecordWriter;
1718
import com.github.fge.jsonschema2avro.writers.SimpleTypeWriter;
1819
import org.apache.avro.Schema;
1920

@@ -33,6 +34,7 @@ public AvroWriterProcessor()
3334
.when(array()).then(ArrayWriter.getInstance())
3435
.when(map()).then(MapWriter.getInstance())
3536
.when(isEnum()).then(new EnumWriter())
37+
.when(record()).then(new RecordWriter())
3638
.getProcessor();
3739
}
3840

src/main/java/com/github/fge/jsonschema2avro/predicates/AvroPredicates.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,37 @@ public boolean apply(final AvroPayload input)
131131
};
132132
}
133133

134+
public static Predicate<AvroPayload> record()
135+
{
136+
return new Predicate<AvroPayload>()
137+
{
138+
@Override
139+
public boolean apply(final AvroPayload input)
140+
{
141+
final JsonNode node = schemaNode(input);
142+
final NodeType type = getType(node);
143+
if (NodeType.OBJECT != type)
144+
return false;
145+
146+
if (node.path("additionalProperties").asBoolean(true))
147+
return false;
148+
149+
if (node.has("patternProperties"))
150+
return false;
151+
152+
final JsonNode properties = node.path("properties");
153+
if (!properties.isObject())
154+
return false;
155+
156+
for (final String s: Sets.newHashSet(properties.fieldNames()))
157+
if (!isValidAvroName(s))
158+
return false;
159+
160+
return true;
161+
}
162+
};
163+
}
164+
134165
private static JsonNode schemaNode(final AvroPayload payload)
135166
{
136167
return payload.getTree().getNode();
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.github.fge.jsonschema2avro.writers;
2+
3+
import com.github.fge.jsonschema.exceptions.ProcessingException;
4+
import com.github.fge.jsonschema.jsonpointer.JsonPointer;
5+
import com.github.fge.jsonschema.processors.data.SchemaHolder;
6+
import com.github.fge.jsonschema.report.ProcessingReport;
7+
import com.github.fge.jsonschema.tree.SchemaTree;
8+
import com.github.fge.jsonschema2avro.AvroWriterProcessor;
9+
import com.google.common.collect.Lists;
10+
import org.apache.avro.Schema;
11+
12+
import java.util.Collections;
13+
import java.util.List;
14+
15+
public final class RecordWriter
16+
extends NamedTypeWriter
17+
{
18+
public RecordWriter()
19+
{
20+
super("record");
21+
}
22+
23+
@Override
24+
protected Schema generate(final AvroWriterProcessor writer,
25+
final ProcessingReport report, final SchemaTree tree)
26+
throws ProcessingException
27+
{
28+
final Schema schema = Schema.createRecord(getName(), null, null, false);
29+
final List<String> list
30+
= Lists.newArrayList(tree.getNode().get("properties").fieldNames());
31+
Collections.sort(list);
32+
33+
final List<Schema.Field> fields = Lists.newArrayList();
34+
35+
JsonPointer ptr;
36+
SchemaHolder holder;
37+
Schema fieldSchema;
38+
39+
for (final String name: list) {
40+
ptr = JsonPointer.of("properties", name);
41+
holder = new SchemaHolder(tree.append(ptr));
42+
fieldSchema = writer.process(report, holder).getValue();
43+
fields.add(new Schema.Field(name, fieldSchema, null, null));
44+
}
45+
46+
schema.setFields(fields);
47+
return schema;
48+
}
49+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.github.fge.jsonschema2avro;
2+
3+
import java.io.IOException;
4+
5+
public final class RecordTest
6+
extends AvroWriterProcessorTest
7+
{
8+
public RecordTest()
9+
throws IOException
10+
{
11+
super("record");
12+
}
13+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
[
2+
{
3+
"jsonSchema": {
4+
"type": "object",
5+
"additionalProperties": false,
6+
"properties": {
7+
"id": { "type": "integer" },
8+
"name": { "type": "string" },
9+
"type": { "enum": [ "food", "drink" ] },
10+
"tags": {
11+
"type": "array",
12+
"items": { "type": "string" }
13+
}
14+
}
15+
},
16+
"avroSchema": {
17+
"type": "record",
18+
"name": "record0",
19+
"fields": [
20+
{ "name": "id", "type": "long" },
21+
{ "name": "name", "type": "string" },
22+
{
23+
"name": "tags",
24+
"type": {
25+
"type": "array", "items": "string"
26+
}
27+
},
28+
{
29+
"name": "type",
30+
"type": {
31+
"type": "enum",
32+
"name": "enum0",
33+
"symbols": [ "food", "drink" ]
34+
}
35+
}
36+
]
37+
}
38+
}
39+
]

0 commit comments

Comments
 (0)