Details
-
Improvement
-
Status: Open
-
Minor
-
Resolution: Unresolved
-
None
-
None
Description
Per https://issues.apache.org/jira/browse/AVRO-485, I have extended Avro's JavaScript support to dynamically generate constructors for Avro records.
Validation of JS objects against Avro schemas is still supported, but the API is different: Avro.validate(schema, obj) instead of Validator.validate(schema, obj). This is a breaking change but may be worth it because there are now several Avro.* funcs.
Code is at https://github.com/sqs/avro/tree/lang-js/lang/js. I will attach a diff.
Here is sample usage. We compile a ManyFieldsRecord constructor function using the Avro schema as input. The constructor function accepts a JS object, which it validates against the Avro schema and then uses to populate the new object's fields. Then ManyFieldRecords objects use Object.defineProperty setters to ensure that the object remains valid Avro.
var manyFieldsRecordSchema = { type: 'record', name: 'ManyFieldsRecord', fields: [ {name: 'nullField', type: 'null'}, {name: 'booleanField', type: 'boolean'}, {name: 'intField', type: 'int'}, {name: 'longField', type: 'long'}, {name: 'floatField', type: 'float'}, {name: 'doubleField', type: 'double'}, {name: 'stringField', type: 'string'}, {name: 'bytesField', type: 'bytes'} ] }; var compiledTypes = Avro.compile(manyFieldsRecordSchema) ManyFieldsRecord = compiledTypes.ManyFieldsRecord, mfr = new ManyFieldsRecord(); test.throws(function() { mfr.nullField = undefined; }); test.throws(function() { mfr.nullField = 1; }); test.throws(function() { mfr.booleanField = 'a'; }); test.throws(function() { mfr.intField = 'a'; }); // TODO: warn if setting int/long field to a non-integer test.throws(function() { mfr.longField = 'a'; }); test.throws(function() { mfr.floatField = 'a'; }); test.throws(function() { mfr.doubleField = 'a'; }); test.throws(function() { mfr.stringField = 3; }); mfr.nullField = null; mfr.booleanField = true; mfr.intField = 1; mfr.longField = 2; mfr.floatField = 3.5; mfr.doubleField = 4.5; mfr.stringField = 'a'; test.equal(mfr.nullField, null); test.equal(mfr.booleanField, true); test.equal(mfr.intField, 1); test.equal(mfr.longField, 2); test.equal(mfr.floatField, 3.5); test.equal(mfr.doubleField, 4.5); test.equal(mfr.stringField, 'a'); // Standard JavaScript JSON API interface: mgr.toJSON(); // --> returns plain JS object (without Avro-validating setters) JSON.stringify(mfr); // --> returns Avro JSON
More examples are in the test dir: https://github.com/sqs/avro/tree/lang-js/lang/js/test.
This is still rough and I am very interested in getting feedback. Thanks!